home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / qbnws303.zip / QBNWS303.NWS < prev    next >
Text File  |  1992-11-15  |  107KB  |  2,270 lines

  1.      Volume  3, Number  3                                 November 15, 1992
  2.  
  3.      
  4.      
  5.      
  6.      
  7.      
  8.      
  9.      
  10.      
  11.      
  12.      
  13.      
  14.      
  15.                    **************************************************
  16.                    *                                                *
  17.                    *                    QBNews                      *
  18.                    *                                                *
  19.                    *      International QuickBASIC Electronic       *
  20.                    *                  Newsleter                     *
  21.                    *                                                *
  22.                    *    Dedicated to promoting QuickBASIC around    *
  23.                    *                  the world                     *
  24.                    *                                                *
  25.                    **************************************************
  26.      
  27.      
  28.      
  29.      
  30.      
  31.      
  32.      
  33.      
  34.      
  35.      
  36.      
  37.      
  38.      
  39.      
  40.      
  41.      
  42.         The  QBNews  is  an electronic newsletter  published  by  Clearware
  43.      Computing. It can be freely distributed providing NO CHARGE is charged
  44.      for  distribution.  The  QBNews is copyrighted in  full  by  Clearware
  45.      Computing.  The  authors  hold  the  copyright  to  their   individual
  46.      articles.  All program code appearing in QBNews is released  into  the
  47.      public  domain.   You  may  do what you  wish  with  the  code  except
  48.      copyright  it.  QBNews  must  be  distributed  whole  and  unmodified.
  49.      
  50.      You can write The QBNews at:
  51.      
  52.           The QBNews
  53.           P.O. Box 507
  54.           Sandy Hook, CT 06482
  55.      
  56.      Copyright (c) 1992 by Clearware Computing.
  57.      
  58.      The QBNews                                                   Page    i
  59.      Volume  3, Number  3                                 November 15, 1992
  60.  
  61.      
  62.  
  63.      ----------------------------------------------------------------------
  64.  
  65.                         T A B L E   O F   C O N T E N T S
  66.  
  67.      
  68.      1.  Beginner's Corner
  69.           Compiling and Linking Made Easy by Arthur Shipkowski .........  1
  70.  
  71.      2.  DataBASICs
  72.           PDT to the Rescue! by Frederick Volking ......................  6
  73.           Announcing PDT -- The Pro~Formance Data Tool ................. 12
  74.  
  75.      3.  Graphic's Workbench
  76.           Dumping Graphics Screens to your Printer by Stephen K. Gartrell  14
  77.  
  78.      4.  Communications Shack
  79.           Implementing XModem in QB by Bryan Leggo ..................... 19
  80.  
  81.      5.  Feature Presentation
  82.           Customizing EGA or VGA TEXT-MODE Fonts By Rob Smetana ........ 26
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.      The QBNews                                                   Page   ii
  119.      Volume  3, Number  3                                 November 15, 1992
  120.  
  121.  
  122.  
  123.      ----------------------------------------------------------------------
  124.                         B e g i n n e r ' s   C o r n e r
  125.      ----------------------------------------------------------------------
  126.  
  127.      Compiling and Linking Made Easy by Arthur Shipkowski
  128.      
  129.      To start off, let me say that this is the first time I've written
  130.      about programming for beginners, or, to rephrase, I'm a beginner at
  131.      writing beginner's articles. <GRIN> Sorry about the bad pun.
  132.      
  133.      To be honest, I wrote this article a little for myself, because I
  134.      don't have a BC/LINK commandline reference.
  135.      
  136.      Compiling from the command line is easier than is sounds or looks,
  137.      based on the QuickBasic manual.
  138.      
  139.      The BC commandline is:
  140.      
  141.         BC sourcefile [,[objectfile],[listfile]] [optionlist] [;]
  142.      
  143.      What does all this idiotic stuff mean? Here goes nothing. The
  144.      sourcefile is your source, not neccesairly with extention, unless
  145.      you're compiling a source file with an extention other than .BAS.
  146.      Objectfile is the name of the object file. If you don't enter this,
  147.      it will have a default of sourcefile.OBJ. However, if you don't enter
  148.      a object file, you'll be prompted for one, as you will for listfile.
  149.      List file is a listing of the source, with some info. It's normally
  150.      useless except for with the /A switch below. The default is Nul.Lst,
  151.      which will output no list file.
  152.      
  153.      The Options are: (For QB 4.5)
  154.      
  155.      /a   - Assembler source in the list file
  156.      
  157.      /ah  - Array Huge! Allows big arrays, and sometimes prevents odd
  158.             errors.
  159.             
  160.      /c:n - set COM buffer size to 'n' bytes. The default if 512 bytes,
  161.             sufficient for most applications except file transfers and
  162.             high baud rates.
  163.             
  164.      /d   - error checking when running, and Ctrl-Break will break out
  165.             of the program. This will also catch overflow errors. However,
  166.             it tends to make your program HUGE!
  167.             
  168.      /e   - enable ON ERROR checking with RESUME linelabel. Doesn't really
  169.             bloat code unless you use line numbers.
  170.             
  171.      /mbf - Use MS binary format numbers (faster, but less accurate) instead
  172.             of IEEE.
  173.             If you don't understand this switch, you don't need it.
  174.             Anyways, there are similar conversion functions built in.
  175.             
  176.      /o   - Stand Alone .EXE (No BRUN needed!)
  177.      
  178.      The QBNews                                                     Page  1
  179.      Volume  3, Number  3                                 November 15, 1992
  180.  
  181.      
  182.      /r   - Store arrays in row-major order (Used for array passing to
  183.             languages like C and Pascal)
  184.             
  185.      /s   - No String compression (like string constants are not put
  186.             together) This serves two functions: A. If you have no like
  187.             string constants, this will reduce .EXE size slightly. Else, it
  188.             will bloat your .EXE. Also, this switch will sometimes stop
  189.             compiler memory errors. (It's a bit of a magic switch, like
  190.             /ah.)
  191.             
  192.      /t   - Terse - no compiler headers, or error messages
  193.      
  194.      /v   - ON EVENT check EVERY STATEMENT. Bloats your code.
  195.      
  196.      /w   - ON EVENT check EVERY LABEL; good if you use labels
  197.             judiciously, otherwise bloats code like /w
  198.             
  199.      /x   - Allows RESUME Next; bloats code like /v
  200.      
  201.      /zi  - Codeview support for using CodeView
  202.      
  203.      /zd  - SYMDEB debugger support (SYMDEB came with MASM 4.0. You
  204.             probably will never need to use this switch.)
  205.      
  206.      Special options availible in BASIC PDS 7.1:
  207.      
  208.      /fpa \ These switches let you decide whether or not to use an
  209.      /fpi / alternate floating point math library. /fpi
  210.             (/FloatingPointIEEE) is the default. It includes a portion
  211.             that on startup, looks for a coprocessor, and either uses or
  212.             not uses the coprocessor. This library is more accurate, but
  213.             is slower, and requires more memory becuase even if a
  214.             coprocessor is present, the other routines to fake a
  215.             coprocessor are still loaded into your precious RAM.
  216.             /fpa (/FloatingPointAlternate) is the other one. It doesn't
  217.             check for a coprocessor, and is faster but less accurate.
  218.             
  219.      /fs  - Enable Far Strings. This gives you more string space, but any
  220.             ASM libraries you use must support it, or you'll get WIERD
  221.             results. If you don't understand it, like /mbf, don't bother:
  222.             It's probably not worth your time anyways.
  223.             
  224.      /g2  - Generate code that runs only on 286s and above. This will
  225.             provide a modest improvement is code size.
  226.             
  227.      /i?  - ISAM options. ISAM stands for Indexed Sequential Access
  228.             Method. If you don't understand this one, don't fret unless
  229.             you're writing a database application in PDS using the ISAM
  230.             that's built in.
  231.             The various options are:
  232.             /ie:memoryneeded - Reserve memoryneeded of EMS memory for
  233.                                ISAM buffers.
  234.             /ib:twokbuffers  - Reserve twokbuffers of 2 kilobyte buffers
  235.      
  236.      The QBNews                                                     Page  2
  237.      Volume  3, Number  3                                 November 15, 1992
  238.  
  239.                                for accessing the EMS.
  240.             /ii:filebuffers  - Reserve filebuffers number of file buffers
  241.                                for file access. This switch is only needed
  242.                                if you are going to use more than 30
  243.                                indexes.
  244.                                
  245.      /lp \ Normally, BC compiles your program based on what OS it is
  246.      /lr / running under - DOS for DOS, OS/2 1.3 for OS/2. These switches
  247.            override that assumption. /lr is for compiling Real Mode (DOS)
  248.            programs under OS/2, and /lp is for compiling Protected Mode
  249.            (OS/2) programs under DOS.
  250.            
  251.      /ot - Optimizes calls. Use it if you have PDS unless you can't use it
  252.            due to some add-on library. This switch basically doesn't put
  253.            a safeguard in for when you use GOSUB in a sub unless you have
  254.            a GOSUB in a SUB. (Just use it, and it will be fine)
  255.            
  256.      /z  - Microsoft Editor support for allowing you to find the lines
  257.            where mistakes are. Don't use it unless you're using ME,
  258.            becuase it bloats code big-time.
  259.      
  260.      Now, for linking.
  261.      
  262.         The LINK commandline is:
  263.      
  264.      LINK [/options] objectfile [objectfile] [libfile.lib] [[[, [exefile]]
  265.           , [mapfile]], [libfile] [libfile] [;]
  266.      
  267.      And what is this jibberish, you may ask? It's all rather simple, like
  268.      the compiler. The options are just those options you want (see below),
  269.      the objectfile is the name of the objectfile produced by the compiler,
  270.      as are the objectfiles in brackets. (yes, there can be more than one.)
  271.      Also, if a library contains only those routines that you want in the
  272.      .EXE, you can put it where the first libfile.lib is, otherwise put it
  273.      where the second libfile is. The exefile is only the name of the .EXE,
  274.      and is assumed to be the name of the first object file. The mapfile is
  275.      a relatively (in my opinion) useless, although it can be used to
  276.      determine DGROUP usage. The final semicolon is not required, and I'm
  277.      not exactly sure why it's there.
  278.      
  279.      LINK Options: (For LINK, only the capitalized letters are neccesary,
  280.      even though you can type in the whole option name.)
  281.      
  282.      /BAtch - Tells LINK it's being run from a batch file, and that it
  283.               shouldn't pause and ask you for libraries, but show a
  284.               warning message instead. Not terribly useful, even in batch
  285.               files, because one misplaced slash will bring everything
  286.               crashing down.
  287.               
  288.      /COdeview - Tells LINK to include Codeview information in the .EXE.
  289.                  must be used with the /zi switch in BC.
  290.                  
  291.      /Exepack - Tells LINK to use a form of executable compression,
  292.                 similar to PKLite or Lzexe or Diet. If you have Lzexe,
  293.      
  294.      The QBNews                                                     Page  3
  295.      Volume  3, Number  3                                 November 15, 1992
  296.  
  297.                 PKLite, or Diet, it's not worthwhile, since they will
  298.                 compress the .EXE better than EXEPACK.
  299.                 
  300.      /Farcalltranslate - A optimizing switch that will reduce program size
  301.                          due to LINK figuring out if a near call will work
  302.                          in place of a farcall. However, in a rare case it
  303.                          may malfunction if you use ON GOTO or any other
  304.                          ON command. If it does, omit this switch.
  305.                          Otherwise, use it.
  306.                          
  307.      /HElp - Tells LINK to display a list of all command switches
  308.              availible. Useful when you forget what the switches are.
  309.              
  310.      /INFo - Tells LINK to display a log of activity on your screen. It
  311.              displays library routine names and object file names. Not
  312.              terribly useful.
  313.              
  314.      /LInenum - Tells LINK to include information for the SYMDEB debugger,
  315.                 in conjunction with the /zd switch in BC. Not terribly
  316.                 useful in most cases, since SYMDEB is an old debugger
  317.                 .
  318.      /Map - Tells LINK to add public symbol names to your map file, as well
  319.             as segment names. Not particularly useful for BASIC
  320.             programming.
  321.             
  322.      /NOExtdict - If you have two or more procedure (SUB/FUNCTION) or data
  323.                   names the same, tells LINK to use the first one it
  324.                   finds, and also tells LINK not to issue an error
  325.                   message. Don't use when unneccesary, because it makes
  326.                   LINK run slower.
  327.                   
  328.      /NOFarcall - Tells LINK not to translate farcalls. This is the
  329.                   default, so this switch is only useful when you have an
  330.                   environment variable with default being /F.
  331.                   
  332.      /NOLogo - Tells LINK not to display its copyright notice.
  333.      
  334.      /NOPackcode - Like /NOF, tells LINK not to pack code, is the default,
  335.                    and isn't useful unless you have an environment
  336.                    variable with /PACKC as the default.
  337.                    
  338.      /Overlayint - Tells LINK to use a different interrupt number for the
  339.                    overlay manager. (Don't know why this is in QB, since
  340.                    it doesn't have the rest of the overlay code, but it's
  341.                    in there anyways.) Not useful unless you have some
  342.                    unusual cards/adapters/software in your computer.
  343.                    
  344.      /PACKCode - Tells LINK to try and squish nearby sections of code
  345.                  together. Most useful in conjunction with /F.
  346.                  
  347.      /PAUse - Tells LINK to pause and allow you to insert a disk before
  348.               writing the .EXE, for use when you're on a floppy-only
  349.               system with limited space.
  350.               
  351.      
  352.      The QBNews                                                     Page  4
  353.      Volume  3, Number  3                                 November 15, 1992
  354.  
  355.      /Quicklib - Used to create a Quick library. (A bit off topic for this
  356.                  article, but it may be covered in a later article.)
  357.                  
  358.      /SEGments: - This switch tells LINK to allocate memory for the
  359.                   specified number of segment names after the colon. By
  360.                   default, LINK reserves room for 128 segments. If you get
  361.                   a 'Too many segments error', try increasing this number.
  362.                   Don't worry about not giving LINK enough room for the
  363.                   rest of the program - if it needs it, it will make a
  364.                   swapfile for that stuff. (Gee, why doesn't it make a
  365.                   swapfile for the segments? I don't know...)
  366.                   
  367.      /STACK: - Lets you set the amount of memory for stacks for a program
  368.                without using CLEAR. If you have PDS, however, the STACK
  369.                statement is a better choice.
  370.      
  371.      The only LINK Option that's in PDS ONLY:
  372.      
  373.      /NODefaultlib - Tells LINK not to use the library name embedded in
  374.                      the object file. (i.e. BRT71EFR.LIB). Accepts a colon
  375.                      after itself with the replacement library name.
  376.      
  377.      To compile a program:
  378.      
  379.         BC MYPROG
  380.         LINK MYPROG
  381.      
  382.      To compile a standalone program:
  383.      
  384.         BC MYPROG /O
  385.         LINK MYPROG
  386.      
  387.      Mind you, you can add other options. Those shown above are the
  388.      absolute minimum that you need.
  389.      
  390.      All of the information presented in this article (and more) can be
  391.      found in Ethan Winer's excellent book, "Basic Techniques and
  392.      Utilites." (Couldn't underline it - oh well.)  I don't mean to sound
  393.      like an advertisement, but his book has an entire chapter on
  394.      compiling, linking, and making libraries, as well as chapters on alot
  395.      of other stuff.
  396.      
  397.      Bibliography
  398.      
  399.      Winer, Ethan. "Basic Techniques and Utilities". Emeryville:
  400.              Ziff-Davis Press, 1991
  401.      
  402.      *********************************************************************
  403.      Arthur Shipkowski is a 15 year old who is the author of HackChek and
  404.      a few other PD and freeware programs. He may be reached at
  405.      1:260/213.2 in FidoNet, 041/002 in GT-Net, or at 75:7716/101 in
  406.      DoorNet.
  407.      *********************************************************************
  408.      
  409.      The QBNews                                                     Page  5
  410.      Volume  3, Number  3                                 November 15, 1992
  411.  
  412.  
  413.  
  414.      ----------------------------------------------------------------------
  415.                                D a t a B A S I C s
  416.      ----------------------------------------------------------------------
  417.  
  418.      PDT to the Rescue! by Frederick Volking
  419.      
  420.      I must tell you up-front that I HATE doing this.  A few years ago I
  421.      wrote a program that we've sold commercially in markets all over the
  422.      world.  But I'm here to recommend that you try a DIFFERENT program:
  423.      the Pro~Formance Data Tool, or PDT.
  424.      
  425.      I've been working with data files for over 18 years: all sizes,
  426.      shapes, formats and kinds.  I can't count the number of times I've had
  427.      to write a Q-&-D (Quick-&-Dirty) program to bail myself (or a
  428.      colleague) out of situations like these:
  429.      
  430.       - You're handed a new task that requires managing someone else's
  431.         data files, files with a structure you don't understand.
  432.      
  433.       - During a download, several records get corrupted.
  434.      
  435.       - While creating a file, NULL characters are accidentally introduced.
  436.      
  437.       - A file has one field too many; or fields are too wide or too short.
  438.      
  439.       - As you're developing or updating a program, something goes wrong
  440.         and you screw up a 15 megabyte data file.
  441.      
  442.       - You're developing a data file and find you have to mass-edit
  443.         several thousand records.
  444.      
  445.      So what do you do?  Write another program to examine the data file?
  446.      To fix corrupted data?  To edit records?  Yeah, sure:  The blind
  447.      leading the blind.  Wouldn't it be nice to have a utility to directly
  448.      view ANY file, to examine the data IN THE RAW, to change it on the
  449.      fly, to figure out its structure, then edit it to your liking!
  450.      
  451.      Every time I had to write a new program, I wished someone would invent
  452.      an editor whose only job was to help me VIEW, UNDERSTAND or EDIT ANY
  453.      file, in a simple, logical, structured way.  I looked around for
  454.      utilities to handle these tasks.  I found several that let me view
  455.      files, or edit one type of file.  But I never found one that let me
  456.      view, interrogate, format and edit ANY file:  simply and easily.
  457.      
  458.      So I gave up looking and wrote my own.  I wrote it mainly for my own
  459.      use; but others took note, and a software distributor picked it up and
  460.      began marketing it commercially under the name of DFD (the Data File
  461.      Doctor).
  462.      
  463.      Although I wrote DFD, I've always known it was a rather crude Q-&-D
  464.      solution.   So after almost 3 years of limping along with DFD, I
  465.      finally found another product that does everything DFD should have
  466.      done.  The program is called PDT (the Pro~Formance Data Tool).  It's
  467.      offered by Rob Smetana of Pro~Formance in San Francisco, California.
  468.      
  469.      The QBNews                                                     Page  6
  470.      Volume  3, Number  3                                 November 15, 1992
  471.  
  472.      
  473.      PDT directly competes with my DFD product.  But that's okay because,
  474.      frankly, I save more $$$ using PDT (in time and effort) than I make
  475.      from DFD.  That says a lot!
  476.      
  477.      Overview
  478.      --------
  479.      
  480.      Very simply, PDT is a wonder to behold!  It offers features no other
  481.      program does; it has everything DFD should have had.  And perhaps most
  482.      important for some, you can try-it-before-you-buy.  PDT is a shareware
  483.      program you can find on CompuServe, America-On- Line and many large
  484.      Bulletin Boards.  You may also contact the author to get a copy:  Rob
  485.      Smetana, at (415) 863-0530.
  486.      
  487.      PDT is an extremely flexible tool to view and edit ANY file --
  488.      including files on networked drives, floppy drives and hard disks.
  489.      Using PDT I've edited tiny 0 and 1 byte files as well as huge, 970
  490.      megabyte files residing on a networked 1 gigabyte Novell file server.
  491.      (PDT can edit files up to 2 gigabytes in size!)
  492.      
  493.      PDT's speed is nothing less than phenomenal.  Working across the
  494.      Novell network, I changed the first byte in this 970 megabyte file,
  495.      then jumped to the end of the file and changed the last byte.  The
  496.      total elapsed time was 15 seconds -- on a networked drive!
  497.      
  498.      Data File Editing
  499.      -----------------
  500.      
  501.      PDT's data file editing tools are unmatched in any program.
  502.      
  503.      For example, if you open a dBase ".DBF" file, PDT automatically
  504.      formats your view of the data into logical rows and columns.
  505.      
  506.      Many programs can do this.  But PDT is unique not only in the long
  507.      list of other features it offers, but also in letting you use this
  508.      same intelligence with virtually ANY fixed-length data file, like
  509.      those created by most programming languages.  PDT can remember
  510.      field-by- field layouts for your data files, and then display that
  511.      data in rows and highlighted columns -- automatically, as you open the
  512.      file!
  513.      
  514.         - You can tab from field to field to easily edit data.
  515.      
  516.         - As you move the cursor to a field, PDT displays the "value"
  517.           of that field -- even fields stored in packed binary format.
  518.      
  519.         - And you can easily edit even packed binary numeric fields.
  520.           PDT automatically converts the binary number to it's decimal
  521.           equivalent, lets you edit it and reconverts the edited value
  522.           back to the binary equivalent before saving it to disk.
  523.      
  524.        Here are some examples of the kind of things I've done with PDT:
  525.      
  526.      
  527.      The QBNews                                                     Page  7
  528.      Volume  3, Number  3                                 November 15, 1992
  529.  
  530.         - We created a new dBase file to store incoming ASCII data.  After
  531.           the data was merged, I found several fields were much wider than
  532.           necessary.  I just moved to the fields, told PDT to shrink them,
  533.           and in seconds it was done -- across thousands of records, saving
  534.           millions of bytes of disk space.  PDT even updated the dBase file
  535.           header automatically.  And PDT can do this just as easily with
  536.           non-dBase data files.
  537.      
  538.         - I needed to copy several hundred records to a new file.  Using
  539.           PDT's Block Mark and Block Export features it took 10 seconds!
  540.      
  541.         - We download a 300 megabyte file from the mainframe.  But we soon
  542.           discovered it had been damaged in transit.  I opened it in PDT,
  543.           set the record length, and within seconds had found the damaged
  544.           area.  It took just 1-2 minutes to restore the damaged data and
  545.           we were on our way -- without writing a line of code.
  546.      
  547.         - I needed to merge records from one data file into the middle of
  548.           another.  I opened both files in PDT (PDT lets you open 4 file
  549.           windows simultaneously), marked the block I wanted to copy,
  550.           jumped to the other file window and selected "Copy/Insert."
  551.           PDT merged the new records instantly.
  552.      
  553.         - We were handed a data file we had to analyze, but had no idea
  554.           what the file structure was.  I opened it in PDT, made a guess
  555.           as to the record length, then leaned on the F9 and F10 keys.
  556.           When you press F9 or F10, PDT adjusts the record length up or
  557.           down, and re-draws the screen to adjust it's "view" of the
  558.           data.  The data literally swings into the proper view.
  559.      
  560.           Once we figured out the record length, it was easy to identify
  561.           where each field began, and what type of field it was (ie.,
  562.           character, integer, double, currency, etc.).  For each field,
  563.           we pressed a key and told PDT what the field name and field type
  564.           were.  When we were done, PDT saved a "structure file" to disk.
  565.           This structure file gave us everthing we needed to create a
  566.           "structure" or "TYPE" in our programs to read the data.  And
  567.           whenever we opened the file again in PDT, PDT read the structure
  568.           file and automatically formatted the data into rows and columns.
  569.      
  570.      List of Features
  571.      ================
  572.      
  573.      The examples above just scratch the surface of what you can do with
  574.      PDT.  Here's a summary of some of the 50 or so options PDT offers.
  575.      
  576.         Block Options:
  577.         --------------
  578.      
  579.         "Blocks" can be records, columns or a continuous stream.  Once you
  580.         mark a block you can Delete it, Export it, Fill it (with any ASCII
  581.         character or phrase), Copy it (to another location in the same file,
  582.         or to another file).  You can even mark a column and Add it up, or
  583.         add Sequence Numbers to it (like unique customer or part numbers).
  584.      
  585.      The QBNews                                                     Page  8
  586.      Volume  3, Number  3                                 November 15, 1992
  587.  
  588.      
  589.         Search & Replace:
  590.         -----------------
  591.      
  592.         Full Search and Replace functions are provided.  These may occur
  593.         forwards or backwards, anywhere in the file or in just the block or
  594.         column you've marked, and can ignore Upper and Lower case.  You can
  595.         Search & Replace using any ASCII character:  0 (null) through 255.
  596.      
  597.         EBCDIC File Support:
  598.         --------------------
  599.      
  600.         One of PDT's most unique features is its EBCDIC file-handling.
  601.      
  602.         You can leave EBCDIC files on disk as-is, and tell PDT to dynamically
  603.         translate them on-the-fly into ASCII.  This lets you view and edit
  604.         data in easy-to-understand ASCII format.  But anything you change
  605.         is automatically converted back to EBCDIC, then saved to disk.
  606.      
  607.         Or, if you prefer, PDT will translate files from EBCDIC to ASCII,
  608.         or vice versa.
  609.      
  610.         File Management:
  611.         ----------------
  612.      
  613.         PDT lets you Create, Delete, Rename or Copy files, or create file
  614.         directories.  A powerful "Join" command lets you merge up to 6
  615.         files while using the smallest amount of disk space possible.
  616.      
  617.         Ease of Use; Getting Help:
  618.         --------------------------
  619.      
  620.         Editing files is much like working in a word processor.  PDT supports
  621.         25-, 43- and 50-line modes in full color or true monochrome.  True
  622.         monochrome works fine on LCD (laptop) displays.
  623.      
  624.         PDT offers both pull-down menus and fast keyboard hotkeys.  And
  625.         most hotkeys are easy to remember (O = Open file, C = Close,
  626.         S = Search, etc.).  PDT supports a mouse for most operations.
  627.      
  628.         Online-help is available for EVERY option.  Just pull down a menu,
  629.         highlight an option, then either press F1 or click the right mouse
  630.         button and a help window pops up.  There's also a large, detailed
  631.         documentation file you can view from inside PDT (or print it).
  632.      
  633.      Flys in the Ointment
  634.      --------------------
  635.      
  636.      In short, PDT lets you view and edit virtually any file up to 2
  637.      gigabytes in size.  And since you can open 4 file windows, you can
  638.      work with up to 8 gigabytes of data at once.
  639.      
  640.       But PDT isn't perfect.  My main gripe is that "I" didn't write it
  641.      .....   Okay, I said it.
  642.      
  643.      The QBNews                                                     Page  9
  644.      Volume  3, Number  3                                 November 15, 1992
  645.  
  646.      
  647.      
  648.      To understand another PDT limitation, you have to know a little about
  649.      how PDT handles file editing.  Unlike an editor or word pro- cessor
  650.      which loads files into memory, PDT loads NOTHING into memory.  When
  651.      you open a file, you're looking at what's on disk (although PDT does
  652.      wonders formatting your view of it).  This fact allows PDT to let you
  653.      view/edit 2-gigabyte files with NO need for extra memory.  And it
  654.      displays files with astonishing speed.
  655.      
  656.      
  657.      But when you turn edit mode on (it's OFF by default) and then change
  658.      something, that change is immediately written to disk.
  659.      
  660.      
  661.      The fact that all changes are immediately saved accounts for PDT's
  662.      restriction that when you Replace something, you must replace it with
  663.      something else of the same length.  A word processor's search and
  664.      replace function can expand or contract things in memory.  But if PDT
  665.      replaced something with something else of a different width, every
  666.      time it found a "hit," PDT would have to re-write the entire disk file
  667.      from that point all the way to the end.  As you can imagine, with
  668.      large files, this would be time-consuming and could be risky.
  669.      
  670.      
  671.      PDT's approach also means that YOU must be careful and should make
  672.      backup copies.  I've NEVER seen PDT damage a file.  But it gives YOU
  673.      the power to muck things up very quickly if you're not careful.  If
  674.      you keep edit mode off you can't do damage.  Turn edit mode on when
  675.      needed.
  676.      
  677.      
  678.         Other "nit piks" include:
  679.      
  680.      
  681.         - PDT offers a calculator offering both decimal and hexadecimal
  682.           calculations.  I'd suggest that it be centered on the screen
  683.           (rather than off to the side), provide a tape readout, and
  684.           support a mouse.
  685.      
  686.      
  687.         - While PDT correctly translates EBCDIC characters to their
  688.           ASCII equivalent, the "values" of EBCDIC packed numeric fields
  689.           don't always translate properly.  That's because translating
  690.           the values of fields requires that you know where fields are and
  691.           what type of field they are -- something PDT often doesn't know.
  692.      
  693.      
  694.         - You can open up to 4 file windows simultaneously, and windows can
  695.           be opened either horizontally or vertically.  No problem there.
  696.           But when you close a window, PDT re-draws all the other windows
  697.           to fill in the now-empty space.  In doing so it often changes
  698.           the original choice of a window's layout:  horizontal/vertical.
  699.      
  700.      
  701.      The QBNews                                                     Page 10
  702.      Volume  3, Number  3                                 November 15, 1992
  703.  
  704.      
  705.      Summary
  706.      -------
  707.      
  708.      If you're a programmer, if you create or use database files, or you
  709.      must maintain or repair data files, you should look at PDT.  You'll be
  710.      amazed at it's flexibility, speed and awesome power.  And since PDT is
  711.      a shareware program, you can try it out for just the cost of a
  712.      download (or a $5 disk fee from a shareware distributor).
  713.      
  714.         Or, you can order it directly from:
  715.      
  716.      
  717.             Rob W. Smetana                    Pro~Formance
  718.                                               132 Alpine Terrace
  719.             (415) 863-0530                    San Francisco, CA  94117
  720.      
  721.      
  722.          EDITOR'S NOTE:   As a special offer to readers of the QBNews,
  723.          you can order PDT for 30% off the normal price:  $69 versus $99.
  724.      
  725.          This offer is good through November, 1992.  And you MUST mention
  726.          the QBNews to take advantage of this offer.
  727.      
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743.  
  744.  
  745.  
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.  
  757.  
  758.      The QBNews                                                     Page 11
  759.      Volume  3, Number  3                                 November 15, 1992
  760.  
  761.      Announcing PDT -- The Pro~Formance Data Tool
  762.      
  763.      Master your data and EXE files.  Edit up to 8 gigabytes at once!
  764.      ================================================================
  765.      
  766.      We're pleased to announce the release of version 2.3 of PDT, the
  767.      Pro~Formance Data Tool.  And to readers of the QBNews, we're now
  768.      offering a SPECIAL DISCOUNT OFFER, good through October, 1992.
  769.      For details see "For Information" at the end of this announcement.
  770.      
  771.      PDT is a very unusual, extremely powerful file editor with tools and
  772.      features NO OTHER PROGRAM offers.  It's designed for:
  773.      
  774.       * programmers
  775.       * developers or users of dBase, other data files, EBCDIC files, etc.
  776.       * anyone who needs to view, edit or manage data files
  777.       * anyone who needs to determine the structure of files, or who
  778.         needs to repair corrupted files
  779.       * anyone who'd like to edit ANY file -- up to 2 gigabytes in size.
  780.      
  781.      2 Gigabyte File Editor
  782.      ======================
  783.      
  784.       * With PDT you can view and edit ANY file:  dBase files, other
  785.         data files, executable files (eg., EXE or COM files), EBCDIC
  786.         files, ASCII files, font files -- any file.
  787.      
  788.       * View and edit ANY SIZE file -- up to two gigabytes!  And you
  789.         can open up to 4 files at once.  View and compare different
  790.         files. Or work in different areas of the same file.  Since each
  791.         file can be up to two gigabytes in size, you can work with up
  792.         to 8 gigabytes of data at once!
  793.      
  794.      Manage database files like you've never been able to before!
  795.      ============================================================
  796.      
  797.       * PDT automatically detects dBase ".DBF" files, formatting your
  798.         view of them into logical rows and columns.
  799.      
  800.       * With other fixed-length data files (like those created by pro-
  801.         grams written in C, Pascal, BASIC, COBOL, etc.), PDT lets you
  802.         easily and quickly define their "structure" -- field names,
  803.         widths, types (string, integer, double, etc.).
  804.      
  805.         And if you're not sure of the structure of a file, PDT can help
  806.         you quickly figure it out.  PDT can even save a "structure file"
  807.         to disk -- which you can use to create the TYPE or structure
  808.         you'd need in your programs to use that file.
  809.      
  810.       * Once PDT knows the structure of a file, records and fields will
  811.         be laid out in logical rows and columns.  You can then easily
  812.         view/edit the file, tabbing quickly to any field.  And you can:
  813.      
  814.         - See values of compressed, packed binary data in easy-to-
  815.      
  816.      The QBNews                                                     Page 12
  817.      Volume  3, Number  3                                 November 15, 1992
  818.  
  819.           understand ASCII.  You can even press a key to edit "packed
  820.           binary" numeric fields.  Enter, say, 9,822, and PDT saves
  821.           it in the appropriate packed binary form.
  822.      
  823.         - Mark blocks (either columns or records) and then:  Export
  824.           them, Copy them, Delete or Fill them, etc.
  825.      
  826.         - Expand or Shrink the width of fields.  This feature is
  827.           incredible!  Imagine moving your cursor to a database
  828.           field, then pressing a key and saying "Expand this field
  829.           10 spaces."  Zap!  It's done.
  830.      
  831.           And PDT will even update the dBase header and its own
  832.           "structure files," if you like, to reflect the change.
  833.      
  834.       * PDT even manages EBCDIC files -- like those found on, or down-
  835.         loaded from, large IBM computers.  PDT can DYNAMICALLY trans-
  836.         late EBCDIC files to ASCII, letting you edit them files in easy-
  837.         to-understand ASCII mode.  Changes are saved to disk in EBCDIC.
  838.         PDT can even translate EBCDIC files to ASCII format, or vice versa.
  839.      
  840.       * PDT can also help you:
  841.         - Repair files -- regardless of their type or size.
  842.         - Determine file structures (record length, field structures, etc.).
  843.         - Edit executable files to update or customize messages or options.
  844.      
  845.      ================================================================
  846.      
  847.      For information on PDT or to order, call or write Rob Smetana at:
  848.      
  849.          Pro~Formance                    (415) 863-0530
  850.          132 Alpine Terrace              San Francisco, CA  94117
  851.      
  852.                      Visa and MasterCard Accepted
  853.      
  854.                SPECIAL 30% DISCOUNT for QBNews readers!
  855.                ========================================
  856.      
  857.      Through November, 1992, readers of the QBNews may order PDT for
  858.      just $69 (+ $4 shipping/handling; $8 outside the US & Canada).
  859.      
  860.              This saves you 30% off the normal $99 price!
  861.      
  862.      BE SURE to mention the QBNews to take advantage of this offer.
  863.      ================================================================
  864.      
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.      The QBNews                                                     Page 13
  874.      Volume  3, Number  3                                 November 15, 1992
  875.  
  876.  
  877.  
  878.      ----------------------------------------------------------------------
  879.                       G r a p h i c ' s   W o r k b e n c h
  880.      ----------------------------------------------------------------------
  881.  
  882.      Dumping Graphics Screens to your Printer by Stephen K. Gartrell
  883.      
  884.      So, you want to print a graphics screen.  Well, you've got two
  885.      choices.  You could leave directions to your users to load DOS's
  886.      GRAPHICS.COM before starting your program.  (You could even do it
  887.      automatically, with a *.BAT file.)  Then, using the QB/QBX.QLB, you
  888.      could make an INT 5 print screen call.
  889.      
  890.      Piece of cake, right?  But, what if your users don't have
  891.      GRAPHICS.COM?  Are you going to see if, for a small fee, Microsoft
  892.      will let you distribute one of their programs with yours?  (Define
  893.      "small".)  Let's say that they do have it, and always remember to load
  894.      it, or that your batch file can cope with the myriad directory
  895.      structures and PATH statements out there.  Are your colors going to
  896.      show up as clearly when printed as they do the way your screen routine
  897.      drew them?  It seems like more control is in order...
  898.      
  899.      What is a "screen" drawing?  It's a series of pixels that you can't
  900.      tell apart _unless_ they are of different colors, the exact numbers of
  901.      pixels being dependent upon screen mode.  What's a typical black ink
  902.      on white paper "printout"?  It's a series of dots that you can't tell
  903.      apart unless they are separated by white, or non-printed, spaces.
  904.      Now, let's see about getting the one onto the other.
  905.      
  906.      Printers, as a rule, are devices that expect all data to arrive one
  907.      byte at a time as ASCII.  This works great for letter writing;
  908.      everyone knows that the standard ASCII set only uses 0d(ecimal) to
  909.      127d- heck, most printers can now deal with the extended ASCII set
  910.      through 255d!  But trying to tell the printer to put "one dot here,
  911.      and then another one to the right and slightly down" doesn't translate
  912.      into ASCII too well.
  913.      
  914.      Before I go on, a brief orientation (pun intended): "Portrait mode" is
  915.      a printout that appears as a normal letter would appear; "Landscape
  916.      mode", for all practical purposes, is printing the screen picture
  917.      "sideways" on the printer sheet.
  918.      
  919.      In graphics mode, we need to set the line feed so that a column of
  920.      dots starts immediately below the column above it.  We can do this by
  921.      sending an "Escape" sequence to the printer.  An "ESCAPE" code, more
  922.      familiarly known as ASCII code 27, alerts the printer to the fact that
  923.      the next sequence of bytes is not ASCII, but should instead be
  924.      interpreted as control codes.  In the example program, a 1/9" line
  925.      feed is used by sending 27d/51d/nd where "n" is the line feed pitch in
  926.      216ths of an inch (in this case, "n" is therefore equal to 24.)
  927.      Likewise, we must decide upon the dot density of the printout and put
  928.      the printer into graphics, or "dot-addressable", mode.  Typically, an
  929.      "IBM/EPSON compatible" printer will offer four choices, namely 60 DPI
  930.      (dots per inch), 120 DPI half-speed (which will ensure good row
  931.      alignment), 120 DPI normal speed, and 240 DPI.
  932.      
  933.      The QBNews                                                     Page 14
  934.      Volume  3, Number  3                                 November 15, 1992
  935.  
  936.      
  937.      When making this choice, the size of the paper, the screen resolution,
  938.      and the print orientation must be taken into consideration.  We are
  939.      (arbitrarily) in SCREEN 12; this gives a 640x480 pixel resolution.
  940.      Since one printer dot will represent one screen pixel, we must divide
  941.      the horizontal ("X") pixels by our printer dot resolution to ensure
  942.      that the printout will fit into a typical 8 1/2" by 11" sheet of
  943.      printer paper.  A bad choice would be 60 DPI; as 640 pixels divided by
  944.      60 "pixels"/inch means that our sheet needs to be 10 2/3" wide.  So
  945.      we'll use 120 DPI half-speed (76d); we do this by sending another
  946.      "Escape" sequence to the printer.  In this case, the format would be:
  947.      
  948.             PRINT #printerfile%, CHR$(27); CHR$(76); CHR$(lsb); CHR$(msb);
  949.         
  950.      Uh, oh!  "Lsb", "msb"?  We've run into that "byte at a time" printer
  951.      communications limitation, yet again.  What the printer wants from the
  952.      program is "how many bytes of raw graphics data should I receive
  953.      before I start looking for control codes or ASCII characters again?".
  954.      Since we are printing the screen in "Portrait" mode, the answer (in
  955.      SCREEN 12) is 640 bytes.  But, since we can only send one byte at a
  956.      time to the printer, we must break the two bytes that 640d needs down
  957.      to meet this.  Thus, the "lsb" would equal 640 MOD 256, while the
  958.      "msb" would equal 640 \ 256.  (While you can calculate this
  959.      beforehand, the example program makes use of a global or SHARED
  960.      variable and does it on the fly.)  For the purposes of this
  961.      explanation, we'll pretend as though we'd sent a "0" msb and an "8"
  962.      lsb, since we are only going to send an 8 pixel by 8 pixel block.
  963.                  
  964.      So far, we've told the printer how far apart to space line feeds, what
  965.      DPI to use, and how many sequential graphics bytes to expect.  Now
  966.      it's time to send the first byte.  We'd better put one together!
  967.      
  968.      First, let's draw a grid on the screen; in the grid will be a pixel
  969.      representation of a circle:
  970.      
  971.      SCREEN 12
  972.      
  973.                                    Screen "X"
  974.      
  975.                                  0 1 2 3 4 5 6 7
  976.                                 ┌─┬─┬─┬─┬─┬─┬─┬─┐
  977.                               0 │ │ │ │ │ │ │ │ │ 2^7 = 128
  978.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤  
  979.                               1 │ │ │ │■│■│ │ │ │ 2^6 =  64
  980.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤  
  981.                               2 │ │■│■│ │ │■│■│ │ 2^5 =  32
  982.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤                 "IBM/EPSON"
  983.                               3 │■│■│ │ │ │ │■│■│ 2^4 =  16    Printer "Graphics"
  984.                  Screen "Y"     ├─┼─┼─┼─┼─┼─┼─┼─┤                Bit-Weighting
  985.                               4 │ │■│■│ │ │■│■│ │ 2^3 =   8
  986.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤  
  987.                               5 │ │ │ │■│■│ │ │ │ 2^2 =   4
  988.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤  
  989.                               6 │ │ │ │ │ │ │ │ │ 2^1 =   2
  990.      
  991.      The QBNews                                                     Page 15
  992.      Volume  3, Number  3                                 November 15, 1992
  993.  
  994.                                 ├─┼─┼─┼─┼─┼─┼─┼─┤  
  995.                               7 │ │ │ │ │ │ │ │ │ 2^0 =   1
  996.                                 └─┴─┴─┴─┴─┴─┴─┴─┘
  997.      
  998.      
  999.      IBM/EPSON compatible (that word...) printers anticipate graphics bytes
  1000.      to to be "bottom up" oriented; i.e. the bottom dot of the eight
  1001.      possible is 2^0 while the top dot is 2^7 (these values are
  1002.      precalculated in the example program, as the call to the ^ function is
  1003.      excruciatingly slow).  We use POINT to get the pixel values, starting
  1004.      with X,Y coordinate (0,7) and working up through the column to (0,0).
  1005.      The first column only has one pixel set; it's 2^4, or 16.  The next,
  1006.      however, has three pixels set.  To hurry things along:
  1007.      
  1008.                                            Printer Byte
  1009.      
  1010.      Column 0 = 2^4                           = 16
  1011.      Column 1 = 2^3 + 2^4 + 2^5 = 8 + 16 + 32 = 56
  1012.      Column 2 = 2^3 + 2^5       = 8 + 32      = 40
  1013.      Column 3 = 2^2 + 2^6       = 4 + 64      = 68
  1014.      Column 4 = 2^2 + 2^6       = 4 + 64      = 68
  1015.      Column 5 = 2^3 + 2^5       = 8 + 32      = 40
  1016.      Column 6 = 2^3 + 2^4 + 2^5 = 8 + 16 + 32 = 56
  1017.      Column 7 = 2^4                           = 16
  1018.      
  1019.      But, what about the colors we invested our circle with?  (O.K., assume
  1020.      half of it is a different color.)  How do we go about conveying
  1021.      "color" to the human eye on a black ink on white paper printout?
  1022.      Remember, the way we can tell those dots apart to start with, is to
  1023.      have "white", or non-printed, intervals between them.  What we can do,
  1024.      therefore, is to control the amount of dots printed for any particular
  1025.      color we are interested in.  We do this by ANDing our weighted pixel
  1026.      bit values with a mask.
  1027.      
  1028.                     BLUE          GREEN           RED           YELLOW
  1029.                    Mask #         Mask #         Mask #         Mask #
  1030.                   01234567       01234567       01234567       01234567
  1031.           2^7    [■■■■■■■■]     [■ ■ ■ ■ ]     [■   ■   ]     [        ]    2^7
  1032.           2^6    [■■■■■■■■]     [ ■ ■ ■ ■]     [        ]     [        ]    2^6
  1033.           2^5    [■■■■■■■■]     [■ ■ ■ ■ ]     [  ■   ■ ]     [  ■     ]    2^5
  1034.           2^4    [■■■■■■■■]     [ ■ ■ ■ ■]     [        ]     [        ]    2^4
  1035.           2^3    [■■■■■■■■]     [■ ■ ■ ■ ]     [■   ■   ]     [        ]    2^3
  1036.           2^2    [■■■■■■■■]     [ ■ ■ ■ ■]     [        ]     [        ]    2^2
  1037.           2^1    [■■■■■■■■]     [■ ■ ■ ■ ]     [  ■   ■ ]     [      ■ ]    2^1
  1038.           2^0    [■■■■■■■■]     [ ■ ■ ■ ■]     [        ]     [        ]    2^0
  1039.      
  1040.                   &&&&&&&&       &&&&&&&&       &&&&&&&&       &&&&&&&&
  1041.                   HHHHHHHH       HHHHHHHH       HHHHHHHH       HHHHHHHH
  1042.                   FFFFFFFF       A5A5A5A5       80208020       00200000
  1043.                   FFFFFFFF       A5A5A5A5       80208020       00000020
  1044.      
  1045.                                        Mask Values
  1046.                                     (Read Vertically)
  1047.      
  1048.      
  1049.      The QBNews                                                     Page 16
  1050.      Volume  3, Number  3                                 November 15, 1992
  1051.  
  1052.      
  1053.      The first mask, &HFF, when ANDed with the result of testing eight
  1054.      pixels for the color blue, returns all of 'em back.  Obviously, this
  1055.      pattern is not necessary, but adding a test in the print subroutines
  1056.      to check for a need to mask the colors may slow it down.  Printer
  1057.      speed will be the deciding factor.
  1058.      
  1059.      By now, you might be thinking: "Why in the world do I have to use
  1060.      eight different masks for one color?".  Good question.  Consider the
  1061.      effect of POINT finding an 8x8 pixel block of solid red.  If you only
  1062.      used one mask (as represented by mask zero in the third block, &H88),
  1063.      then it would be printed as:
  1064.      
  1065.                                     [■■■■■■■■]
  1066.                                     [        ]
  1067.                                     [        ]
  1068.                                     [        ]
  1069.                                     [■■■■■■■■]
  1070.                                     [        ]
  1071.                                     [        ]
  1072.                                     [        ]
  1073.      
  1074.      Stripes!!  Through the use of MOD, however, we can cycle through all
  1075.      eight masks and eliminate this effect, as the example program will
  1076.      show.
  1077.      
  1078.      You may have noted that with four mask sets, the pixels will need to
  1079.      be read four times.  POINT, as you may have observed in earlier
  1080.      experiences, is not particularly fast.  What the example program does
  1081.      is read as many pixels as will be needed with a FOR/NEXT, and then
  1082.      store the returned values in an array for later processing.  In turn,
  1083.      rather than make four printing passes, the results of each masking AND
  1084.      pass are ORed into one output byte.  This transfers all the necessary
  1085.      output dots as expeditiously as is possible.
  1086.      
  1087.      Now, we know what to send.  How do we get it there?  The easiest way
  1088.      is to bypass QB/PDS and go through the BIOS using printer interrupt
  1089.      &H17.  Since we don't want to overwork our fingers, we'll also open
  1090.      the printer as a "file" using OPEN "lpt1:BIN" FOR OUTPUT AS #filenum%.
  1091.      The use of the BIN keyword in the OPEN statement means that QB/PDS
  1092.      shouldn't count characters and emit a carriage return, the timing of
  1093.      which we wish to control ourselves.  (You may experiment, and find
  1094.      that LPRINT and PRINT # fail miserably in place of the INT &H17 call
  1095.      for sending actual graphics bytes.)
  1096.      
  1097.      On to the subject of "aspect ratios".  First, what is it?  It's the
  1098.      ratio of a screen's width to it's height.  Ordinarily, your CRT has
  1099.      approximately a 1.33 (4:3) aspect ratio.  (Speaking of it's _physical_
  1100.      dimensions.)  This means that screen output tends to be distorted as a
  1101.      result of being "stretched" horizontally.  As a practical experiment,
  1102.      PSET a 50 pixel line horizontally, and then another vertically, in
  1103.      SCREEN 7.  Then measure the resultant lines as they appear on your
  1104.      CRT.  A significant difference exists, with the horizontal line being
  1105.      longer even though the number of pixels is identical.  Those pixels
  1106.      
  1107.      The QBNews                                                     Page 17
  1108.      Volume  3, Number  3                                 November 15, 1992
  1109.  
  1110.      must not be square, we must conclude.
  1111.      
  1112.      Now add differing screen resolutions.  In 320x200 modes, the aspect
  1113.      ratio is 4.8:3; in 640x480 mode, it's back to 4:3.  (Here, I'm
  1114.      referring to the ratio of pixels wide to pixels high.)  QB/PDS
  1115.      graphics commands usually offer you the ability to adjust the aspect
  1116.      ratio of graphics objects, either by passing an "aspect" value, or by
  1117.      simply altering line lengths. 
  1118.      
  1119.      What happens when we print a screen?  A printer dot is the same size,
  1120.      period. (Pun also intended.)  The aspect compensation that was done
  1121.      for your screen now has an exaggerated effect at your printer.  In
  1122.      320x200 modes, for instance, a circle that was perfectly round on your
  1123.      screen, since it was made a little taller to compensate for the extra
  1124.      1.8 in pixels width to height ratio, will appear taller and skinnier
  1125.      on paper in Portrait mode.  Unless, as the example program does, you
  1126.      adjust for it by either duplicating adjacent dots, or perhaps by
  1127.      adding additional blank columns.  The VidConfig function call of the
  1128.      example program sets SHARED variables automatically in the event that
  1129.      you wish to use aspect compensation.
  1130.      
  1131.      One last note, and then on to the example program.  Recall the
  1132.      statements alluding to telling the printer "how many graphics bytes to
  1133.      expect".  If you should interrupt program operation before that number
  1134.      has been reached, and are unable to resume printing _precisely_ where
  1135.      the program left off, just go ahead and reset your computer, or cycle
  1136.      power on your printer, or make a call to interrupt &H17 function &H01
  1137.      (initialize printer).  Otherwise, your printer will still be expecting
  1138.      graphics characters, and will treat all control or ASCII characters
  1139.      sent to it as graphics characters!!!
  1140.      
  1141.      Also:  Most, if not all, printers come with a manual that has the
  1142.      applicable ESCAPE codes listed in an appendix.  Check it out!!
  1143.      
  1144.      Code for this article can be found in GPRINT.ZIP.
  1145.      
  1146.      *********************************************************************
  1147.      Steve Gartrell spent six years in the U.S. Army, primarily concerned
  1148.      with various aspects of digital and analog communications. He obtained
  1149.      an Associate's Degree in Electronics Technology from Ohio University
  1150.      and has been programming in QuickBasic for the last several years,
  1151.      with Assembly language enhancements as needed.
  1152.      *********************************************************************
  1153.      
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.      The QBNews                                                     Page 18
  1165.      Volume  3, Number  3                                 November 15, 1992
  1166.  
  1167.  
  1168.  
  1169.      ----------------------------------------------------------------------
  1170.                      C o m m u n i c a t i o n s   S h a c k
  1171.      ----------------------------------------------------------------------
  1172.  
  1173.      Implementing XModem in QB by Bryan Leggo
  1174.      
  1175.      XModem, far from state-of-the-art in transfer protocols, does have one
  1176.      great advantage: it's simple, easy to implement and therefore
  1177.      available in more places than any other. Some communications programs
  1178.      may only have one or two binary protocols and XModem is usually one of
  1179.      them so it's especially good to have it available if you're writing a
  1180.      host program or BBS in order to reach the greatest number of users.
  1181.      XMODEM.BAS is a simple terminal program with procedures to send and
  1182.      receive with the XModem protocol. Three variations on the protocol are
  1183.      handled within the code.
  1184.      
  1185.      The three basic types are the original protocol (Standard), XModem CRC
  1186.      and XModem-1k which is sometimes referred to as YModem (non-batch
  1187.      variety). Most transfer protocols use some method of error checking to
  1188.      see if the proper characters were sent and received. Standard XModem
  1189.      used a Checksum, adding the bits of each byte. Next came XModem CRC
  1190.      which replaced the one byte Checksum with the more accurate and
  1191.      reliable 16 bit (2 bytes) CRC. The third variation, XModem-1k may use
  1192.      EITHER Checksum or CRC. It is different from the others in it's block
  1193.      size, i.e. that it sends 1024 file data bytes at a time instead of the
  1194.      usual 128.
  1195.      
  1196.      All variations only send so many characters at a time until it can be
  1197.      verified that the transmission was complete and correct or until an
  1198.      error is detected. The groupings of characters from the file being
  1199.      sent are referred to as "blocks", and so we say that XModem-1k has a
  1200.      block of size 1024 bytes (1k). Standard uses a block of 128 bytes. But
  1201.      in addition to bytes from the file being sent we must also have some
  1202.      controlling characters (the checksum being an example) to smooth the
  1203.      transmission of each block. Therefore we use the term "packets" to
  1204.      describe the block of file data bytes plus all necessary control
  1205.      characters. The Standard XModem packet is constructed as follows
  1206.      (where <xyz> denotes a single byte):
  1207.      
  1208.      <Soh> + <Block Number> + <Complement Block Number> + Block +<Checksum>
  1209.      
  1210.      <Soh> is Ascii Value 1, or CHR$(1) in Basic. Other common Ascii codes
  1211.      that we will use include <Stx> (Ascii 02), <Ack> (Ascii 6) to
  1212.      ACKnowledge, <Nak> (Ascii 21) to Negatively AcKnowledge, <Can> (Ascii
  1213.      24) to CANcel and <Eot> (Ascii 4) to indicate End Of Transmission.
  1214.      These are defined globally in XMODEM.BAS.
  1215.      
  1216.      The Block Number is a single byte and thus may represent a number from
  1217.      1 to 255. To further verify transmissions both Sender and Receiver
  1218.      keep track of which block is being sent and this number advances
  1219.      accordingly.  Obviously, whether the block is 128 bytes or 1024, many
  1220.      files will be large enough to require more than 255 blocks so the
  1221.      Block Number will wrap to be 1 again after 255.
  1222.      
  1223.      
  1224.      The QBNews                                                     Page 19
  1225.      Volume  3, Number  3                                 November 15, 1992
  1226.  
  1227.      The Complement Block Number is just that, (Block Number XOR 255), so
  1228.      that as Block Numbers go 1, 2, 3, 4, 5.... the Complement will be 254,
  1229.      253, 252, 251....
  1230.      
  1231.      Block is the group of 128 or 1024 bytes from the file (depending on
  1232.      type of XModem in use) and <Checksum> is the Checksum value of all the
  1233.      bytes in that Block.
  1234.      
  1235.      
  1236.      XModem is "receiver driven" which means that the receiving end
  1237.      controls the flow of information by sending back characters as
  1238.      signals. These signals are used to alert the sender of errors and for
  1239.      timing purposes, i.e. the receiver will tell the sender when it is ok
  1240.      to send the next packet (or to resend a packet with errors detected).
  1241.      Not receiving data on time, called "timing out" is an error in itself
  1242.      and can cause the transmission to be aborted if chronic. Timing is
  1243.      used in both the process of getting each character of a packet and in
  1244.      initiating the transfer, sometimes called "handshaking" here.
  1245.      
  1246.      Handshaking can take a few seconds because Sender and Receiver operate
  1247.      independently and may start at different times. The Sender waits while
  1248.      the Receiver sends out the start signal every few seconds, waiting for
  1249.      a response from the Sender. The starting signal is <Nak> for Checksum
  1250.      and <C> for CRC mode.
  1251.      
  1252.      Below is a diagram of typical successful Standard XModem transmission.
  1253.      In this example we have an example file of say 493 bytes which would
  1254.      require 4 blocks of 128 bytes, i.e. transmitting 4 packets. The
  1255.      transfer is initiated by the Receiver sending a <Nak> and waiting for
  1256.      a response. If no response comes within the alloted time it would send
  1257.      another <Nak> until getting a response or it has reached it's maximum
  1258.      number of attempts. In this example we will also say that due to line
  1259.      noise one packet had a glitch in one of the block characters the first
  1260.      time it was sent out, which caused an incorrect Checksum value.
  1261.      
  1262.      
  1263.           Sender                                        Receiver
  1264.           ------                                        --------
  1265.      01.                                           <---  <Nak>
  1266.      02. <Soh> <1> <254> Block <ChkSum> --->
  1267.      03.                                           <---  <Ack>
  1268.      04. <Soh> <2> <253> Block <ChkSum> --->
  1269.      05.                                           <---  <Ack>
  1270.      06. <Soh> <3> <252> Block <ChkSum> --->       (Error Detected!)
  1271.      07.                                           <---  <Nak>
  1272.      08. <Soh> <3> <252> Block <ChkSum> --->
  1273.      09.                                           <---  <Ack>
  1274.      10. <Soh> <4> <251> Block <ChkSum> --->
  1275.      11.                                           <---  <Ack>
  1276.      12. <Eot>
  1277.      13.                                           <---  <Ack>
  1278.      
  1279.      The error occurred in Step 06, where the corrupted data led to an
  1280.      improper checksum. So, instead of an <Ack> which would indicate the
  1281.      
  1282.      The QBNews                                                     Page 20
  1283.      Volume  3, Number  3                                 November 15, 1992
  1284.  
  1285.      packet was okay, the receiver sends a <Nak> (NOT Acknowledged) in Step
  1286.      07 so that the Sender will know to RE-transmit that same Block, that
  1287.      is, Block 3. It does so in Step 08. The Sender doesn't know what KIND
  1288.      of error it was. It could have been a Bad Block, Bad Complement Block
  1289.      Number or some other error but as long as it knows to transmit the
  1290.      same block again we have a good chance of recovering.
  1291.      
  1292.      FIRST BYTE OF A PACKET, THE PACKET "HEADER"
  1293.      
  1294.      The first byte of each packet is especially important. For a normal
  1295.      Standard packet with data following it should always be <Soh> but it
  1296.      also may be a <Can> to Cancel transmission in case of a "fatal" error
  1297.      or an <Eot> as in Step 12 to indicate that there is no more data and
  1298.      the transmission is complete. If the first byte is anything but <Soh>,
  1299.      <Stx>, <Can> or <Eot> then it is an error.
  1300.      
  1301.      Since the first byte will not necessarily be followed by block data (a
  1302.      <Can> or an <Eot> are not followed by a full packet), in coding it we
  1303.      will get the first byte and check what it is before going on to get
  1304.      the remainder of the packet.
  1305.      
  1306.      FATAL ERRORS
  1307.      
  1308.      Excessive numbers of errors, even minor errors like timeouts cause a
  1309.      transfer to be aborted. What is "excessive" though, may depend on the
  1310.      programmer. Originally XModem retried all errors 10 times and used
  1311.      varying timeout values for handshaking and character timeouts in
  1312.      packets. No Carrier detected is also a fatal error. And both sender
  1313.      and receiver are allowed to manually abort transmission which can be
  1314.      handled by the fatal error routine.
  1315.      
  1316.      In XMODEM.BAS a timeout occurs after 8 seconds without data and the
  1317.      initial connection will be tried 10 times, first several times in CRC
  1318.      mode and the remainder with Standard XModem. Up to 10 errors will be
  1319.      tolerated in the transmission of packets.
  1320.      
  1321.      XMODEM-CRC
  1322.      
  1323.      XModem CRC differs from Standard in two ways. First in the way the
  1324.      transfer is initiated. Instead of the Receiver sending a <Nak> to
  1325.      indicate readiness it would send the letter C (Ascii 67). For example,
  1326.      in order to try CRC Mode in the diagrammed example above then Step 01
  1327.      would have the Receiver send a "C".
  1328.      
  1329.      Since the term XModem is sometimes used loosely and it's not always
  1330.      apparent whether a BBS or Comm program are supporting XModem CRC we
  1331.      want implementations of CRC Mode to be downward compatible with
  1332.      Standard Mode. To acheive this we have the Receiver try BOTH C and
  1333.      <Nak>. In XMODEM.BAS for example we try C the first 4 times and then
  1334.      try <Nak> the remaining times. If the Sender hasn't responded by that
  1335.      time then it is a fatal error. You may want to modify this, or employ
  1336.      another scheme, perhaps one that alternates between sending <C>s and
  1337.      <Nak>s in order to speed up handshaking.
  1338.      
  1339.      
  1340.      The QBNews                                                     Page 21
  1341.      Volume  3, Number  3                                 November 15, 1992
  1342.  
  1343.      The other difference for CRC of course, is that we replace the
  1344.      Checksum byte with a CRC value. That means that a CRC packet will be
  1345.      one byte longer than a Standard one since it is a 16 bit CRC and
  1346.      requires two bytes, first high, then low, as illustrated below:
  1347.      
  1348.      <Soh> <Block #> <Complement Block #>  Block <CRCHighByte> <CRCLowByte>
  1349.                                                  ------------- ------------
  1350.      
  1351.      XMODEM-1K
  1352.      
  1353.      This may be run in either Standard or CRC Mode. The difference is in
  1354.      the size of the block which will be 1024 bytes, except possibly for
  1355.      the final portion of a file where some blocks will be 128 bytes.  More
  1356.      about that below.  XModem-1k must therefore be able to accept any
  1357.      combination of blocks of EITHER size. That means that the sender must
  1358.      have a way of notifying the receiver of which block size to
  1359.      anticipate. When we are sending a block of 1024 bytes we will use
  1360.      <Stx> as the first byte of the packet instead of <Soh>. In CRC Mode 1k
  1361.      this would be:
  1362.      
  1363.      <Stx> <Block #> <Complement Block #>  Block <CRCHighByte> <CRCLowByte>
  1364.      -----
  1365.      
  1366.      PADDING WITH CHR$(0)
  1367.      
  1368.      Each Block sent by XModem must be either 128 bytes or 1024 bytes.  But
  1369.      most file lengths will not be evenly divisible by these so on the
  1370.      final block transmitted we pad with nulls if necessary. In XModem-1k
  1371.      that could mean an awful lot of padding, so rather than enlarge the
  1372.      file received to the nearest multiple of 1k the sender will switch to
  1373.      128 byte blocks for the final part of the file. That way we will not
  1374.      enlarge the file any more than the nearest multiple of 128. THAT is
  1375.      why XModem-1k must be able to handle any combination of 128 or 1024
  1376.      byte blocks. And depending on which size a block is, we will as usual
  1377.      send a first byte of either <Soh> or <Stx> in each packet.
  1378.      
  1379.      SETTING THE TIMEOUT LENGTH REMOTELY
  1380.      
  1381.      Originally XModem allowed the Receiver to notify the Sender of the
  1382.      Timeout value being used (in seconds), apparently for better
  1383.      coordination. Looking at old XModem code it appears to me that to do
  1384.      so the Receiver would send CHR$(14) + "T " followed by an Ascii String
  1385.      of the timeout length, but since this is not detailed in the docs I
  1386.      consulted I can't be sure. In testing and looking at the transmissions
  1387.      of other BBS XModems it appears that setting a timeout value is not
  1388.      usually done anyway. Ignoring the "T " + value should not cause any
  1389.      problems since anything but a <Nak> or <C> can be ignored while
  1390.      initiating.
  1391.      
  1392.      XMODEM PACKETS RE-CAP
  1393.      
  1394.      Block refers to Block of Text from File (128 bytes, 1024 for
  1395.      XModem-1K) Packet Refers to Block + Extra "Control" Characters, i.e. :
  1396.      
  1397.      
  1398.      The QBNews                                                     Page 22
  1399.      Volume  3, Number  3                                 November 15, 1992
  1400.  
  1401.       Standard: SOH + BlockCt + Complement BlockCt + Block + CheckSum
  1402.      XModemCRC: SOH + BlockCt + Complement BlockCt + Block + CRC (Hi & Low)
  1403.      
  1404.      XModem-1K: STX + BlockCt + Complement BlockCt + Block + CheckSum
  1405.         CRC-1K: STX + BlockCt + Complement BlockCt + Block + CRC (Hi & Low)
  1406.      
  1407.      ** Sometimes may also use 128 byte blocks with SOH replacing STX
  1408.      
  1409.      
  1410.      NOTES ABOUT THIS IMPLEMENTATION (XMODEM.BAS)
  1411.      
  1412.      When Receiving:
  1413.      
  1414.      Bytes in blocks of 128 received are not immediately written to disk
  1415.      but are temporarily stored in an array B$(). After the 4th one, when
  1416.      512 bytes total have accumulated they are all written to disk in order
  1417.      to save time used in accessing the disk. This is a convention due to
  1418.      CP/M's use of 512 byte disk granularity and may not be necessary on
  1419.      other machines.
  1420.      
  1421.      A Repeated Block Number is handled by the Error Warning routine even
  1422.      though it is not really a serious error. If the Sender is erroneously
  1423.      resending a packet that was just received without errors that means
  1424.      that the <Ack> the Receiver just sent to Acknowledge it was garbled as
  1425.      in Step E of of the example diagrammed below. Even though the Block
  1426.      Number was not the expected one processing can continue.  Since it is
  1427.      not necessary to resend that packet the repeated block number and
  1428.      packet are virtually ignored by the receiver and it sends an <Ack>
  1429.      instead of <Nak> as in Step G below.
  1430.      
  1431.           Sender                                                 Receiver
  1432.           ------                                                 --------
  1433.      A.                                                      <---  C
  1434.      B. <Soh> <1> <254> Block <CRCHigh> <CRCLow> --->
  1435.      C.                                                      <---  <Ack>
  1436.      D. <Soh> <2> <253> Block <CRCHigh> <CRCLow> --->
  1437.      E. *** Corrupted <Ack> ***                              <---  <Ack>
  1438.      F. <Soh> <2> <253> Block <CRCHigh> <CRCLow> --->          (Repeated)
  1439.      G.                                                      <---  <Ack>
  1440.      H. <Soh> <3> <252> Block <CRCHigh> <CRCLow> --->
  1441.                                                            and so on....
  1442.      
  1443.      Timeouts are measured by marking the time with TIMER and checking the
  1444.      difference from the Marked Time to the current one.  Crossing midnight
  1445.      is usually a problem here, returning a large difference but one faulty
  1446.      character timeout won't matter much in the scheme of things since the
  1447.      routine will tolerate several more timeouts.
  1448.      
  1449.      Many implementations of XModem will use different timeout values for
  1450.      the initial handshaking process and later when reading packets from
  1451.      the Sender.  XModem documents suggest a 10 second timeout per attempt
  1452.      to initiate and then going to a 1 second timeout thereafter, which
  1453.      could be a bit risky with a 1,024 byte block size and a slow CRC
  1454.      routine that works on full blocks (as XMODEM.BAS does).
  1455.      
  1456.      The QBNews                                                     Page 23
  1457.      Volume  3, Number  3                                 November 15, 1992
  1458.  
  1459.      
  1460.      Whereas you might want at least 5 seconds between attempted
  1461.      handshakes, a 1 second timeout for block characters would often be
  1462.      fine, but I couldn't see any serious disadvantages in having a longer
  1463.      packet/character timeout.
  1464.      
  1465.      They also suggest one very long timeout of a minute for the Sender.
  1466.      But since the Receiver can eventually fatally timeout itself and will
  1467.      then send a <Can> to the Sender, XMODEM.BAS has no Sender timeout at
  1468.      all.
  1469.      
  1470.      
  1471.      When Sending:
  1472.      
  1473.      We are using one routine to handle both 128 and 1k sized blocks so it
  1474.      is easier to open the file to be sent at length 128 for both cases.
  1475.      If sending 128 then we can send immediately after GETting the next
  1476.      block from disk. If sending 1024 then we can GET 8 times (8 * 128 =
  1477.      1024), appending each disk read to Blk$ until ready to send the entire
  1478.      1024 bytes.
  1479.      
  1480.      In CRC-1k the calculated number of TtlBlocks is based on a block size
  1481.      of 1024. But since the final few packets may indeed be 128 byte blocks
  1482.      this leads to situation where more packets than the value of TtlBlocks
  1483.      are sent.  This would give percentages greater than 100 in the display
  1484.      so an extra check is added for this and the Video Bar indicating
  1485.      transfer progress.
  1486.      
  1487.      The estimated transfer time is very rough. It's based on the number of
  1488.      bytes being sent per packet, Ttlblocks and Baud rate. It does not take
  1489.      into account timing delays, CRC calculation time, or resends. I
  1490.      experimented with an empirical approach, using a measured "average"
  1491.      time per packet but these estimates were even worse! Let me know if
  1492.      you find a better way to estimate.
  1493.      
  1494.      CYCLICAL REDUNDANCY CHECK
  1495.      
  1496.      The CRC isn't even remotely optimized. (Some things sure would be
  1497.      easier if QuickBASIC had ShiftLeft and ShiftRight functions). In fact,
  1498.      you can improve the speed of the CRC simply removing the FOR J loop
  1499.      and explicitly writing the group of three statements within eight
  1500.      times, replacing the Power(J)'s with 128,64,32,16 and so on.
  1501.      
  1502.      As is, on my computer the CRC is fast enough and there is no danger of
  1503.      it causing a timeout error. But I'm sure that linking with an external
  1504.      .OBJ CRC routine or using Assembler or a table lookup approach would
  1505.      be faster and may even be necessary on some slower machines. Or to be
  1506.      safe you could just increase the timeout limit. You could also
  1507.      calculate the CRC incrementally as each byte comes in but this would
  1508.      unnecessarily complicate the TimedGet Function.
  1509.      
  1510.      CODE STRUCTURE
  1511.      
  1512.      I originally began this program by adapting GWBASIC code that was not
  1513.      
  1514.      The QBNews                                                     Page 24
  1515.      Volume  3, Number  3                                 November 15, 1992
  1516.  
  1517.      structured in approach. Continuing to use GOTOs in the Error Handling
  1518.      is partly held over from that but also not a bad idea in itself. I
  1519.      rarely use them for anything but Error Handling. It's certainly better
  1520.      than jumping out of a a GOSUB routine and leaving the return address
  1521.      on the stack. Feel free to impose a few DO LOOPs if you're unduly
  1522.      offended by them.
  1523.      
  1524.      PROBLEMS
  1525.      
  1526.      This program is not bulletproof. If the receiver should erroneously
  1527.      receive a <Can> or <Eot> due to line noise as the first byte of a
  1528.      packet it may respectively cancel transmission or prematurely close
  1529.      the file. The chances of this happening are actually quite low but it
  1530.      would be nice to have a surefire and standardized way to handle such
  1531.      garbaged transmissions.  XMODEM.BAS in the SendXModem Procedure
  1532.      attempts to handle a false <Can> by looking for at least 2 more <Can>s
  1533.      afterwards (where the BlockCt and Complement BlockCt would normally be
  1534.      in a packet). XModem commonly uses 5 <Can>s followed by 5 <BS>s to
  1535.      trigger cancellation, although many implementations will only require
  1536.      one <Can>. In fact, using using CHR$(24) to Cancel is not even part of
  1537.      the official standard. (Note: the purpose of the BackSpaces is to
  1538.      erase the extra <Can>s if they should show on screen at the other
  1539.      end.)
  1540.      
  1541.      The PurgeBuffer routine removes any characters still waiting in COM to
  1542.      be processed. Some timing has been added so that at least half a
  1543.      second must also go by since the last buffered character was junked.
  1544.      Only then will it return, hopefully all extraneous characters removed.
  1545.      Just checking for EOF can cause problems when machine speed is so much
  1546.      faster than baud rate that the loop back to the EOF test is done
  1547.      before more characters can be received.
  1548.      
  1549.      EXTERNAL PROTOCOLS
  1550.      
  1551.      XMODEM.BAS is setup to allow easy calling of an external protocol.
  1552.      Define the SendExternal$ and RecvExternal$ variables to execute the
  1553.      desired program from DOS with desired parameters. Since you may need
  1554.      to specify a filename you can use the tilde ( ~ ) as a placeholder for
  1555.      the filename.
  1556.      
  1557.      <ACK>-MENTS
  1558.      
  1559.      I'd like to thank Keith Hampton for helping me down the road of ruin
  1560.      called transfer protocols, without whom none of this programming would
  1561.      have been necessary. He provided much info, including passing on
  1562.      technical documents such as the XModem Compendium by Chuck Forsberg. I
  1563.      suggest you consult that if you'd like to add YModem batch mode to
  1564.      your repertoire.
  1565.      
  1566.      The files for this article can be found in XMODEM.ZIP.
  1567.      
  1568.  
  1569.  
  1570.  
  1571.      The QBNews                                                     Page 25
  1572.      Volume  3, Number  3                                 November 15, 1992
  1573.  
  1574.  
  1575.  
  1576.      ----------------------------------------------------------------------
  1577.                      F e a t u r e   P r e s e n t a t i o n
  1578.      ----------------------------------------------------------------------
  1579.  
  1580.      Customizing EGA or VGA TEXT-MODE Fonts By Rob Smetana
  1581.      
  1582.      Question : : :
  1583.      
  1584.       * Have you ever wanted to replace the dull, ordinary text-mode
  1585.         font your PC (or your users' PCs) normally uses?
  1586.      
  1587.       * Would you like to be able to display different types of
  1588.         messages in different fonts -- in text mode?
  1589.      
  1590.       * Or how about special symbols:  Copyright or Trademark symbols,
  1591.         arrows, pointers, etc.
  1592.      
  1593.       * Would you like to be able to tuck several text fonts into
  1594.         your programs, and then just "CALL fontname" to change fonts?
  1595.      
  1596.      If you answered "YES" to any of these questions, you'll find these
  1597.      routines to change text fonts a valuable addition to your tool kit.
  1598.      
  1599.      FontDemo.Bas
  1600.      ------------
  1601.      
  1602.      If you have an EGA or VGA monitor, you might want to STOP READING
  1603.      and run FontDemo.Bas.  Some of the things we'll discuss below
  1604.      might make more sense if you've already seen them in action.  (By
  1605.      the way, if, when you run FontDemo, you're curious what "P~F" and
  1606.      "Pro~Formance" mean, they're our trademark and company name.)
  1607.      
  1608.      To run FontDemo.Bas, you MUST load one of the two Quick Libraries
  1609.      we included.  The ".QLB" files contain text fonts we'll CALL; and
  1610.      they also contain the Interrupt routines needed to invoke the BIOS
  1611.      video services.
  1612.      
  1613.        In QB:            qb fontdemo /L fonts45
  1614.      
  1615.        In QBX:          qbx fontdemo /L fonts7
  1616.      
  1617.      NOTE QB 4.x users:  Before running FontDemo, you MUST comment out
  1618.      one line.  Please read the comments near the top of FontDemo.
  1619.      
  1620.      ALSO NOTE:  FontDemo contains some routines you may find useful
  1621.      even if you don't need to change text fonts:
  1622.      
  1623.        QB.Monitor      helps you determine the type of monitor is being
  1624.                        used -- AND the number of screen rows (25/43/50).
  1625.        SideLogo        displays a scrolling banner -- in 4 directions.
  1626.      
  1627.      Changing Fonts:  EGA or VGA Required, and Text-Mode Only
  1628.      --------------------------------------------------------
  1629.      
  1630.      
  1631.      The QBNews                                                     Page 26
  1632.      Volume  3, Number  3                                 November 15, 1992
  1633.  
  1634.      Note that monochrome, CGA and Hercules monitors simply can't
  1635.      change text-mode fonts using the routines we'll describe.  Their
  1636.      hardware doesn't support it.  We've seen no harm done by trying
  1637.      to switch fonts on these monitors.  But nothing happens.
  1638.      
  1639.      Also, we're talking about changing text-mode fonts -- those used
  1640.      by DOS, QB.Exe or QBX.Exe, many editors and word processors,
  1641.      spreadsheets, etc.  While it's possible to use the same fonts
  1642.      we'll discuss here in graphics mode, we won't be covering that.
  1643.      
  1644.      One advantage of using custom fonts in graphics mode is you can
  1645.      use many different fonts on the same screen.  And these fonts
  1646.      can vary in size -- from tiny to huge.
  1647.      
  1648.      In text mode however, 2 character sets may be active at once (al-
  1649.      though you can re-map parts of each character set to obtain many
  1650.      different fonts).  And the size of text-mode fonts is, in general,
  1651.      limited to the size of the "character cell" (each character appears
  1652.      in a cell or grid that's usually 8 dots wide and either 16, 14 or 8
  1653.      dots high).  So in text mode we have a limited amount of space to
  1654.      work in, which constrains how large text characters can be (al-
  1655.      though you can use 2 or more characters to "piece together" larger
  1656.      symbols or letters.  For an example, note the large "P~F" logo dis-
  1657.      played when you run FontDemo.Bas).
  1658.      
  1659.      (Note:  Well discuss how to change the basic text font here.  Our
  1660.      TextFont Programmer's Edition offers ASM routines to let you display
  1661.      two different fonts at the same time AND MANY different mouse cursor
  1662.      shapes -- arrows, hour glasses, and many others -- in text mode!)
  1663.      
  1664.      Your Possibilities Still Abound
  1665.      -------------------------------
  1666.      
  1667.      But even with just one character set available in text mode, you
  1668.      still have many options.
  1669.      
  1670.      For example, you can re-map just certain characters (like control
  1671.      codes or high ASCII characters) and then print these to create
  1672.      unusual effects.  And you can re-map these characters several
  1673.      different times in your program -- the appearance of all other
  1674.      characters remains constant.  At the beginning of your program,
  1675.      re-map Chr$(255) to display a Copyright symbol.  Later, re-map
  1676.      Chr$(255) to display a pointer.
  1677.      
  1678.        FontDemo.Bas illustrates printing Chr$(255) and control charac-
  1679.        ters to display Copyright and Registered Trademark symbols, and
  1680.        a "pointing hand" text-mode cursor.  It also illustrates using
  1681.        high ASCII characters to print text sideways, upside down,
  1682.        underlined or in Italics -- while we're printing normal text
  1683.        in normal ways!
  1684.      
  1685.      You can also display text and then quickly switch fonts.  As you
  1686.      switch fonts, the appearance of the on-screen text changes -- the
  1687.      screen is NOT cleared.  FontDemo.Bas also has examples of this.
  1688.      
  1689.      The QBNews                                                     Page 27
  1690.      Volume  3, Number  3                                 November 15, 1992
  1691.  
  1692.      
  1693.      What you need
  1694.      -------------
  1695.      
  1696.      To replace the standard text font on EGA/VGA monitors you need 2
  1697.      things, and a 3rd is desirable.
  1698.      
  1699.       1.  First you need fonts.  We've included some here; and we also
  1700.           included a small, "freeware" font editor with which you can
  1701.           design your own fonts.  Later, we'll mention some other sources.
  1702.      
  1703.       2.  You need the code to do it.  That's the easy part.
  1704.      
  1705.       3.  Desirable is a RAM-resident TSR that's able to restore your
  1706.           font when programs change screen modes.
  1707.      
  1708.           - Once you change fonts, any change in screen modes (to,
  1709.             say, graphics mode or to 43- or 50-line mode) will restore
  1710.             the default font.  So if you're working in a spreadsheet
  1711.             with your new font, and view a graph, the TSR should
  1712.             restore your text-mode font when you return to text mode.
  1713.      
  1714.           - Later we'll explain how one might go about developing this
  1715.             TSR.  (We send one to registered users of the TextFont pro-
  1716.             gram we recently released.  TextFont offers about 50 fonts!)
  1717.      
  1718.      Switching Fonts:  The Basics
  1719.      ----------------------------
  1720.      
  1721.      Changing text mode fonts is quite simple.  We'll illustrate two
  1722.      ways to do it:
  1723.      
  1724.       1. By loading fonts from disk.
  1725.      
  1726.          - This option lets you keep many font files on disk (or in a
  1727.            font library, or concatenated to the end of EXE files).
  1728.            Storing fonts on disk lets you keep EXE sizes small, while
  1729.            giving you access to dozens or hundreds of alternatives.
  1730.      
  1731.       2. By CALLing fonts by name (eg., CALL Script), using the ASM
  1732.          files that Font2Asm can create for us.
  1733.      
  1734.          - This option is easy and fast; it's ideal when you need few
  1735.            font changes, or when you want to re-map just a few charac-
  1736.            ters.  And since you'll assemble the ASM files and LINK the
  1737.            OBJ fonts to your programs, this option minimizes the
  1738.            chances that on-disk font files will get lost or damaged.
  1739.      
  1740.      Changing Fonts:  Using the BIOS Video Services
  1741.      ----------------------------------------------
  1742.      
  1743.      Regardless of whether you load fonts from disk or CALL FontName,
  1744.      the actual work of changing fonts is done by a BIOS video service
  1745.      often called the Character Generator Routine.
  1746.      
  1747.      The QBNews                                                     Page 28
  1748.      Volume  3, Number  3                                 November 15, 1992
  1749.  
  1750.      
  1751.       * All BIOS video functions are accessed via Interrupt 10h.
  1752.      
  1753.       * The service (function) we want (the Character Generator) is 11h.
  1754.      
  1755.       * For more information on these services, consult Ralph Brown's
  1756.         interrupt guides, or works by Norton or Duncan.
  1757.      
  1758.      To change fonts, we simply need to:
  1759.      
  1760.       1. Determine several things about the font we want to load:
  1761.      
  1762.          - How many characters we want to re-map (1 to 256).
  1763.          - How wide each character's bit-map is (usually 8, 14 or 16).
  1764.          - And where (ie., beginning with which ASCII character) we
  1765.            want to begin re-maping characters.
  1766.      
  1767.       2. Invoke Int 10h, service 11h.
  1768.      
  1769.      That's it!  And please notice two things about step #1:
  1770.      
  1771.       * WE specify how many characters we'll re-map (replace), which
  1772.         gives us tremendous flexibility.  We can replace all ASCII
  1773.         characters, just 1-2 characters, or anything in between.
  1774.      
  1775.         - All of the examples you'll see if you run FontDemo.Bas
  1776.           re-map just part of the 256 character ASCII set.  For
  1777.           example, many examples re-map just the English language
  1778.           characters -- Chr$(33) to Chr$(126).  We did NOT re-map
  1779.           the line-draw characters, since that's often unnecessary
  1780.           and undesirable (doing so can cause gaps in lines), and
  1781.           this helped us keep font files small.
  1782.      
  1783.       * WE specify which characters we want to re-map.
  1784.      
  1785.         - You can re-map some of the 256 ASCII characters you'll never
  1786.           use in your programs.  For example, in FontDemo.Bas, we re-
  1787.           mapped some control characters and some high ASCII characters.
  1788.           This let us print normal text in normal ways, and ALSO print
  1789.           text sideways, upside down, underlined and in italics.
  1790.      
  1791.           -- To print underlined text, we simply loaded underlined
  1792.              versions of A-Z and a-z into the "slots" normally reserved
  1793.              for ASCII characters 128 and beyond.
  1794.      
  1795.           -- Then, to print a normal "A" we printed "A."  To print an
  1796.              underlined "A," we printed Chr$(129) -- whose ASCII code
  1797.              was 64 higher than the normal "A."
  1798.      
  1799.      How to Load Fonts From Disk
  1800.      ---------------------------
  1801.      
  1802.      Keeping fonts in disk files (or font libraries) gives you access
  1803.      to dozens or hundreds of different fonts.  We included two font
  1804.      
  1805.      The QBNews                                                     Page 29
  1806.      Volume  3, Number  3                                 November 15, 1992
  1807.  
  1808.      files:  Italics.14 and Uline.14 (underlined).
  1809.      
  1810.      Here's how we loaded the Italics font in FontDemo.Bas.
  1811.      
  1812.       * All the hard work is done by a subroutine in FontDemo called
  1813.         LoadFontFile.  To load a font, just CALL LoadFontFile, speci-
  1814.         fying which on-disk file to use, and describing the font.
  1815.      
  1816.      
  1817.       * We mentioned earlier that to load a font we must know several
  1818.         things about that font:
  1819.      
  1820.         - How many characters we want to re-map (1 to 256).
  1821.      
  1822.           Both of our sample font files contain 64 characters --
  1823.           basically just the English language A-Z and a-z.  So step
  1824.           #1 is to indicate how many characters we'll be loading:
  1825.      
  1826.                NumberChars = 64
  1827.      
  1828.         - How wide each character's bit-map is (usually 8, 14 or 16).
  1829.      
  1830.           In our sample fonts, each character is represented by
  1831.           14-byte strings.  They correspond to an 8 x 14 character
  1832.           cell which is useable on BOTH EGA and VGA monitors.
  1833.      
  1834.                CharWidth = 14
  1835.      
  1836.         - And where (ie., beginning with which ASCII character) we
  1837.           want to begin re-maping characters.
  1838.      
  1839.           Many font files you find on BBSs (or those you create with
  1840.           VGAFONT.COM) contain all ASCII characters from 0 to 255.  To
  1841.           load one of these, you'd indicate that the 1st character to
  1842.           re-map is Chr$(0).  When you CALL LoadFontFile, you'd set
  1843.           FirstChar = 0.
  1844.      
  1845.           But in both Italics.14 and Uline.14, the first character is
  1846.           "@" --- ASCII character 64.  If we wanted to replace normal
  1847.           characters with Italic versions, we'd set FirstChar = 64.
  1848.           Then all English-language text would be displayed in Italics.
  1849.      
  1850.           However, in FontDemo.Bas we wanted to be able to display
  1851.           BOTH normal AND Italic text.  So we loaded Italics.14 into
  1852.           characters 128 and beyond -- 64 higher than our 1st character.
  1853.      
  1854.                FirstChar = 128
  1855.      
  1856.       * In summary, our CALL to LoadFontFile looks something like this
  1857.         (we'll explain the parameter "UsingFarStrings" shortly):
  1858.      
  1859.           FontFile$ = "ITALICS.14"
  1860.           NumberChars = 64
  1861.           CharWidth = 14
  1862.      
  1863.      The QBNews                                                     Page 30
  1864.      Volume  3, Number  3                                 November 15, 1992
  1865.  
  1866.           FirstChar = 128
  1867.      
  1868.           Call LoadFontFile (FontFile$, CharWidth, FirstChar,   _
  1869.                              NumberChars, UsingFarStrings)
  1870.      
  1871.      Here's what you'll find if you examine LoadFontFile:
  1872.      
  1873.       1. First we read the font file in one gulp.
  1874.      
  1875.          FontFile = FREEFILE
  1876.      
  1877.          OPEN FontFile$ FOR BINARY AS #FontFile
  1878.      
  1879.          a$ = SPACE$(LOF(FontFile))    ' read entire font in one gulp
  1880.      
  1881.          GET #FontFile, , a$           ' do it
  1882.      
  1883.          CLOSE #FontFile
  1884.      
  1885.       2. Next, since we'll be invoking a BIOS interrupt by CALLing
  1886.          InterruptX, we must translate our numeric variables into
  1887.          a form InterruptX can handle.
  1888.      
  1889.          - Near the top of FontDemo we created a TYPE called
  1890.            RegTypeX.  It consists of several integer variables
  1891.            corresponding to the "registers" one must often set
  1892.            up before invoking BIOS or DOS functions.  (Earlier
  1893.            issues of the QBNews have discussed CALL INTERRUPT;
  1894.            so we won't belabor the point here.)
  1895.      
  1896.          - We then dimensioned this TYPE, declaring it SHARED so
  1897.            all routines in FontDemo had access to it.
  1898.      
  1899.                DIM SHARED Registers AS RegTypeX
  1900.      
  1901.          - So, before invoking our BIOS function, we set up the
  1902.            appropriate registers.  Here's a summary of what's
  1903.            needed to switch fonts.
  1904.      
  1905.            CX  --  # of characters you're loading       (1 - 256)
  1906.      
  1907.            DX  --  ASCII code of 1st character to remap (0 - 255)
  1908.      
  1909.            BH  --  # of bytes in each bit-map           (eg., 8, 14, 16)
  1910.      
  1911.            BL  --  block to load                        (0)
  1912.      
  1913.            ES:BP   pointer to the string/array containing your font
  1914.      
  1915.            Once we set up the registers, we invoke interrupt 10h,
  1916.            function 11h TWICE -- once to load our font, and then
  1917.            to set it (or to select it, or to turn it on).
  1918.      
  1919.          Here's how we set up the call to InterruptX in LoadFontFile.
  1920.      
  1921.      The QBNews                                                     Page 31
  1922.      Volume  3, Number  3                                 November 15, 1992
  1923.  
  1924.      
  1925.            Registers.CX = NumberChars   ' # of characters in the font
  1926.      
  1927.            Registers.DX = FirstChar     ' DX = where to begin loading.
  1928.      
  1929.                                         ' This is the ASCII # of the
  1930.                                         ' character where you want to
  1931.                                         ' begin loading your font.  It
  1932.                                         ' is often 0 or 33 or 128 or ???
  1933.      
  1934.            ' NOTE: FirstChar + NumberChars should never exceed 256!
  1935.      
  1936.      
  1937.            Registers.BX = CharWidth * 256  ' BH = # of bytes in each
  1938.                                         ' character's bit map (eg., 8,
  1939.                                         ' 14, 16).  Since we must set BH,
  1940.                                         ' we multiply CharWidth by 256.
  1941.      
  1942.                                         ' BL (block to load) will be 0
  1943.      
  1944.          - Next, we point ES:BP to the Segment and Address of the
  1945.            string containing our font data.  THIS is where the
  1946.            parameter "UsingFarStrings" comes into play.
  1947.      
  1948.            -- If you're using QBX (or compiling using BC7's FAR
  1949.               string option) you's use SSEG to determine the
  1950.               segment in which the font string (a$) resides.
  1951.      
  1952.            -- But in QB (or if you're compiling using BC7's NEAR
  1953.               string option), you'd use VARSEG to get the segment.
  1954.      
  1955.      
  1956.            IF UsingFarStrings THEN
  1957.      
  1958.               Registers.ES = SSEG(a$)   ' Segment if using QBX/BC7 FAR strings
  1959.      
  1960.            ELSE
  1961.      
  1962.               Registers.ES = VARSEG(a$) ' Segment w/ QB or BC7's NEAR strings
  1963.      
  1964.            END IF
  1965.      
  1966.            Registers.BP = SADD(a$)      ' The address of our string
  1967.      
  1968.       3. Finally, we invoke interrupt 10h TWICE:  first to LOAD the
  1969.          font, and then to SET it.
  1970.      
  1971.            Registers.AX = &H1100        ' Use Function 11h, Service 0 (Load)
  1972.                                         ' of Interrupt 10h.
  1973.                                         ' AH = 11h - The function we want
  1974.                                         ' AL =   0 - Load user font
  1975.      
  1976.            InterruptX &H10, Registers, Registers  ' Invoke BIOS service 10h
  1977.      
  1978.      
  1979.      The QBNews                                                     Page 32
  1980.      Volume  3, Number  3                                 November 15, 1992
  1981.  
  1982.      
  1983.      
  1984.            Registers.AX = &H1103        ' Use Function 11h, Service 3 (Set)
  1985.                                         ' AH = 11h - The function we want
  1986.                                         ' AL =   3 - Set (Select) our font
  1987.      
  1988.            Registers.BX = 0             ' BL = Which block to load (parallels
  1989.                                         ' what we did above when loading it)
  1990.      
  1991.            InterruptX &H10, Registers, Registers  ' Invoke BIOS service 10h
  1992.      
  1993.      That's it!  Any text that's currently on your screen will now
  1994.      appear in the new font.  The screen will NOT clear, although
  1995.      you might see it "twitch."  That's because these BIOS functions
  1996.      DO cause a screen-mode set, but without clearing the screen.
  1997.      
  1998.      What Could Go Wrong
  1999.      -------------------
  2000.      
  2001.      If your screen suddenly turns into unreadable gibberish, it may
  2002.      be because:
  2003.      
  2004.       * The font file did NOT exist on disk.  Who knows what was loaded.
  2005.      
  2006.       * You erred when specifying one of the parameters (eg., you said
  2007.         each bit map was 14-bytes when it was really 16).  In this case
  2008.         characters might be readable, but each may have pieces of the
  2009.         previous (or next) character.
  2010.      
  2011.       * The "UsingFarStrings" parameter was wrong.  (eg., you were
  2012.         working in QBX, but then compiled using the NEAR string option).
  2013.         This would point to the wrong area of memory; and again, who
  2014.         knows what you're looking at.
  2015.      
  2016.      Since errors like this can turn everything unreadable -- including
  2017.      what you see in QB/QBX -- you might want to put SCREEN , 0 near the
  2018.      top of programs you're developing.  This helps ensure QB/QBX restore
  2019.      the default font when you return to the environment.  Also get
  2020.      familiar with CALL RestoreDefault (MonitorType).
  2021.      
  2022.      CALLing FontName;  Creating CALLable Fonts
  2023.      ---------------------------------------------------------------
  2024.      
  2025.      An even easier way to change text fonts is to LINK them to your
  2026.      programs and then just CALL FontName!  To do this:
  2027.      
  2028.       * Create (or find) some font files (see "Sources of Fonts" below).
  2029.      
  2030.       * Run Font2Asm.Bas. CORRECTLY answer each question it asks you.
  2031.         Font2Asm is not included here.
  2032.      
  2033.       * Font2Asm will create an ".ASM" file (with the name you
  2034.         specify).  Assemble this ".ASM" file using MASM 5.1 + to
  2035.         create an ".OBJ" file.
  2036.      
  2037.      The QBNews                                                     Page 33
  2038.      Volume  3, Number  3                                 November 15, 1992
  2039.  
  2040.      
  2041.       * You can then use LIB and LINK to:
  2042.      
  2043.         - Add this ".OBJ" to LIB files:
  2044.      
  2045.               LIB FONTS +ITALICS;
  2046.      
  2047.         - Add them to your Quick Libraries:
  2048.      
  2049.               LINK /Q/SEG:512  ITALICS, , NUL, BQLB45;  (or QBXQLB with PDS)
  2050.      
  2051.         - Or LINK them to your programs:
  2052.      
  2053.               LINK  MYPROG, , NUL, BCOM45 + FONTS (+ other LIB files);
  2054.      
  2055.               LINK  MYPROG, , NUL, BCL71ENR + FONTS (+ other LIB files);
  2056.      
  2057.      When you "CALL FontName," you're actually doing the same thing
  2058.      that LoadFontFile does -- it's just easier and it looks different.
  2059.      For example, here's part of SYMBOLS.ASM created by Font2Asm:
  2060.      
  2061.         Mov  CX, 10                    ;# of characters in our font
  2062.      
  2063.         Mov  DX, 14                    ;starting character (we're re-
  2064.                                        ;mapping control characters here)
  2065.      
  2066.         Mov  BH, 16                    ;# bytes per character
  2067.      
  2068.         Xor  BL, BL                    ;block to load (0)
  2069.      
  2070.         Mov  AX, CS                    ;Load ES:BP with font's Segment:Offset
  2071.         Mov  ES, AX                    ;get code segment
  2072.         Mov  BP, Offset SYMBOLSData    ;and our address
  2073.      
  2074.         Mov  AH, 11h                   ;LOAD font using function 11h,
  2075.         Xor  AL, AL                    ;service 0
  2076.      
  2077.         Push BP                        ;Int 10 can trash BP on some PCs
  2078.         Int  10h
  2079.         Pop  BP
  2080.      
  2081.         Mov  AH, 11h                   ;Now SELECT (set) the font using
  2082.         Mov  AL, 3                     ;function 11 (in AH), svce 3 (in AL)
  2083.         Xor  BX, BX                    ;load block 0
  2084.      
  2085.         Push BP
  2086.         Int  10h
  2087.         Pop  BP
  2088.      
  2089.         Ret
  2090.      
  2091.         SymbolsData: DB 0,0,124,130,154,162,162,162,154,130,124,0,0,0,0,0
  2092.                         ;  Copyright   (C)
  2093.                      DB 0,0,124,130,178,170,178,170,170,130,124,0,0,0,0,0
  2094.      
  2095.      The QBNews                                                     Page 34
  2096.      Volume  3, Number  3                                 November 15, 1992
  2097.  
  2098.                         ;  Registered Trademark (R)
  2099.      
  2100.         etc . . .
  2101.      
  2102.      Notice "SymbolsData" above.  It's followed by one line of numbers
  2103.      for each character we're re-mapping ("DB" is analogous to BASIC's
  2104.      DATA statement).  Each number is the ASCII code for a character.
  2105.      Why not use strings?  Because MASM (like QB/QBX) chokes when
  2106.      certain characters appear in files.  When you assemble this file,
  2107.      each line will be converted to the same character bit-map that
  2108.      appeared in the original font file.  Also note there are 16
  2109.      numbers on each line -- corresponding to "Mov  BH, 16    ;# bytes
  2110.      per character" that appeared earlier.
  2111.      
  2112.      Eliminating Fluff;  Why 14-point VGA fonts?
  2113.      -------------------------------------------
  2114.      
  2115.      Most on-disk font files you'll find, including those created by
  2116.      VGAFONT.COM, may contain lots of unnecessary fluff.  For example,
  2117.      VGAFONT's files are 4096 bytes (16 times 256).  They include
  2118.      Chr$(0) and Chr$(255) which are blank.  Unless you edit these,
  2119.      why replace blanks with blanks?
  2120.      
  2121.      And if you examine the character bit maps, you'll find that most
  2122.      characters have "white space" around them (Chr$(0)).  When you
  2123.      print characters, this white space accounts for the spacing
  2124.      between letters in words, and the space between lines.  It's
  2125.      not until you get to the high ASCII characters (especially line
  2126.      drawing ASCII 176 and beyond) that the characters start to fill
  2127.      the entire character cell -- so lines and boxes will connect.
  2128.      
  2129.      The point is, once you decide which characters you want to re-map,
  2130.      you may find you can delete characters, and also delete some of
  2131.      the white space following each character.  Doing so can eliminate
  2132.      hundreds or thousands of bytes from your EXEs or font files.  An
  2133.      EASY way to do this is to let Font2Asm do its thing, then edit
  2134.      the ASM files.  Delete characters, then change one or more of the
  2135.      parameters (# of characters, starting character, # bytes/character).
  2136.      
  2137.      That's why our fonts contained 14-byte bit maps, even though they
  2138.      work fine on VGA monitors with 8x16 character cells.  We just
  2139.      eliminated the trailing white space.  Since we weren't re-mapping
  2140.      control codes or line-draw characters (which DO require 16-byte bit
  2141.      maps for VGA use), we were free to eliminate the excess baggage.
  2142.      
  2143.      Sources of Fonts
  2144.      ----------------
  2145.      
  2146.      We included a "freeware" program (VGAFONT.COM) you can use to
  2147.      create or edit font files (if you have a VGA monitor).  VGAFONT.DOC
  2148.      explains how to use it.
  2149.      
  2150.      When run, VGAFONT looks for a file called VGAFONT.DTA.  If found,
  2151.      VGAFONT loads it and lets you edit it.  Therefore, if you have
  2152.      
  2153.      The QBNews                                                     Page 35
  2154.      Volume  3, Number  3                                 November 15, 1992
  2155.  
  2156.      other font files, just rename them VGAFONT.DTA and then run VGAFONT
  2157.      to edit them.
  2158.      
  2159.      Fonts you edit with VGAFONT MUST have 16-byte bit maps.  If they
  2160.      don't, this small program can read, say, 14-byte bit maps, and
  2161.      save them to another file, padding each character with Chr$(0).
  2162.      
  2163.           Defint A-Z
  2164.      
  2165.           Open "Italics.14" For Binary as #1
  2166.           Open "VGAFONT.DTA" For Binary as #2
  2167.      
  2168.           FontIn$  = String$(14, 0)     '...change "14" as appropriate
  2169.      
  2170.           FontOut$ = String$(16, 0)     '...be sure to use "0" here, not "32"
  2171.      
  2172.           Do Until EOF (1)
  2173.              Get #1 , , FontIn$
  2174.              Lset OutFont$ = FontIn$
  2175.              Put #2 , , FontOut$
  2176.           Loop
  2177.      
  2178.           Close
  2179.      
  2180.      You may already have several files that contain fonts.  For
  2181.      example, DOS often comes with files like GRAFTABL.COM or EGA.CPI
  2182.      that contain fonts (although they're not very interesting).  Your
  2183.      word processor, spreadsheet or Windows may also include font files.
  2184.      Please be aware that many of these fonts are copyrighted.  So your
  2185.      use of their contents may be constrained.
  2186.      
  2187.      There are also several public domain programs that include fonts.
  2188.      Try your local BBS or CompuServe.  Scan for EGA*.* and VGA*.*.
  2189.      
  2190.      Maintaining Fonts Despite Screen-Mode Changes
  2191.      ---------------------------------------------
  2192.      
  2193.      We mentioned earlier that once you change fonts, any change in
  2194.      screen modes (to, say, graphics mode or to 43- or 50-line mode)
  2195.      will restore the default font.
  2196.      
  2197.      You can't prevent this from happening, but you can use a TSR to
  2198.      restore YOUR choice of text fonts when you return to text mode or
  2199.      25-line mode.  (We send such a TSR to registered users of the
  2200.      TextFont program we recently released.)
  2201.      
  2202.      You can create this TSR in many languages including BASIC (eg.,
  2203.      by using Crescent's PDQ).  Here's the general design:
  2204.      
  2205.        1.  Before going resident, your TSR loads a font into, say, a
  2206.            string variable you'll later use to restore YOUR font.
  2207.      
  2208.        2.  After going resident, your TSR watches for a screen-mode
  2209.            change to text mode.  If detected, it re-loads your font.
  2210.      
  2211.      The QBNews                                                     Page 36
  2212.      Volume  3, Number  3                                 November 15, 1992
  2213.  
  2214.            Specifically, you'd:
  2215.      
  2216.            - Trap Int 10h, Function 0h (Set Video State).
  2217.      
  2218.            - If you detect a "Set Text Mode" (eg., AL = 3h or 7h),
  2219.              restore the font.  SUB LoadFontFile in FontDemo.Bas has
  2220.              the BASIC code you'd need to restore the font.  Modify it
  2221.              to point to the string variable you loaded earlier.
  2222.      
  2223.      That's it.  Such a TSR can even work in Windows.  For example, when
  2224.      we open a DOS window, our TSR restores the font we selected.
  2225.      
  2226.      All files for this article can be found in TEXTFONT.ZIP.
  2227.      
  2228.      *********************************************************************
  2229.      Rob Smetana holds a Ph.D. in Organizational Psychology and runs
  2230.      Pro~Formance, a firm that not only provides organizational consult-
  2231.      ing but also develops software.
  2232.      
  2233.      Among the 25+ programs they offer are TextFont (with 50+ alternatives
  2234.      to the default EGA/VGA text font), P-Screen (a QB/PDS screen-design
  2235.      and screen-library system that was reviewed in an earlier QB News),
  2236.      P~F Presents (a presentation program often used for prototyping
  2237.      programs, program demos, tutorials, training, etc.), PDT (the
  2238.      Pro~Formance Data Tool, designed to help you view and edit any
  2239.      file, especially dBase or any other fixed-length data files --
  2240.      like font files!), and The Printer (a programmers' utility with
  2241.      printer codes for over 700 different printers).
  2242.      
  2243.      Rob can be reached at (415) 863-0530, on CompuServe (72117,1360),
  2244.      or on the FidoNet Quik_Bas echo.
  2245.      *********************************************************************
  2246.      
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.      The QBNews                                                     Page 37
  2269.  
  2270.